PHP preg_替换最后一个下划线之后出现的任何文本
我可以使用PHP preg_替换最后一个下划线之后出现的任何文本,php,regex,preg-replace,preg-match,Php,Regex,Preg Replace,Preg Match,我可以使用explode(或者使用strrpos)来实现这一点,但我更喜欢使用preg\u replace,因为我认为应该快一点(不是吗?)。另外,它简洁优雅 其目的是,给定一个类似于a_b_c的字符串,以获得另一个sting,其中最后一个后面的字符被传递的字符串替换 我不擅长正则表达式。我得找时间在书房里买一本好书。无论如何,我已经尝试过这个正则表达式'/u(.*)$/'作为匹配字符串末尾的参数,捕获最后一个下划线后面的任何字符 我的论证有什么不对 // Do it using explode
explode
(或者使用strrpos
)来实现这一点,但我更喜欢使用preg\u replace
,因为我认为应该快一点(不是吗?)。另外,它简洁优雅
其目的是,给定一个类似于a_b_c
的字符串,以获得另一个sting,其中最后一个
后面的字符被传递的字符串替换
我不擅长正则表达式。我得找时间在书房里买一本好书。无论如何,我已经尝试过这个正则表达式'/u(.*)$/'
作为匹配字符串末尾的参数,捕获最后一个下划线后面的任何字符
我的论证有什么不对
// Do it using explode
function foo($string, $replacement)
{
$pieces = explode('_', $string);
array_pop($pieces);
return implode('_', array_merge($pieces, array($replacement)));
}
// Do it using regular expression (not working)
function bar($string, $replacement)
{
return preg_replace('/_(.*)$/', $replacement, $string);
}
echo foo('a_b_c', 3); // Prints a_b_3
echo bar('a_b_c', 3); // Prints a3 wrong!!!
“/([^]+)$/”
与所有内容匹配,但最后一个下划线后有一个下划线
注意:不需要将下划线与此匹配。这样,在进行替换时,不会丢失最后一个下划线。如果您很接近,您要查找的模式是:
([^_]*)$
这将只匹配不带下划线的文本,尽可能靠近字符串末尾。它也不包括下划线,因为替换字符串不使用
$1
来指定匹配的组 问题是第一个下划线匹配。您需要下划线后面的任何内容,但下划线除外:
'/_([^_]*)$/'
正则表达式
/\uu(.*)$/
匹配下划线,后跟任意文本,后跟字符串结尾。没有什么能阻止“任何文本”包含下划线,默认情况下,匹配器将选择最左边、最长的匹配。所以在“a_b_c”中,它在“a”之后匹配
您可以通过将
(与任何字符匹配)替换为字符类[^\u]
(与下划线以外的任何字符匹配)来修复此问题
此外,由于您没有对捕获的组执行任何操作,因此不需要括号。而且,基于您的示例,您不想替换下划线本身,因此应该将其从正则表达式中删除
function bar($string, $replacement)
{
return preg_replace('/[^_]*$/', $replacement, $string, 1);
}
如果您关心速度,那么使用strpos将比preg_replace更快。所有的字符串函数(据我所知)都比正则表达式函数慢
下面是一个速度测试:根据您的常用搜索字符串和PCRE版本,
preg\u replace
或strrpos
可能效果最好:
功能
测试线束
请注意(至少在我使用PHP5.4.0的设置中),preg_replace
为strrpos
提供了一次运行,直到最后一个下划线前面有大量下划线为止
编辑:我插入了套件,除非要替换的下划线靠近字符串的开头,否则它不会很好地执行:
a_b_c:
usingPreg2: 0.40s
abcdefghijklmnopqrstuvwxy_z:
usingPreg2: 1.91s
a_bcdefghijklmnopqrstuvwxyz:
usingPreg2: 0.38s
a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z:
usingPreg2: 1.04s
这看起来像一个表情符号,但我认为它应该起作用:
return preg_replace('/(.*_).*/', $replacement, $string);
我有个问题。我想要正则表达式!现在我有两个问题;)preg比简单的字符串函数慢。。大多数cases@Hajo同意-在某些情况下,速度要慢得多,这取决于实际使用的正则表达式;看看我的答案!这是可行的,但当您真正想要的是一组更严格的匹配字符时,使用非贪婪匹配并不是最佳做法。面对格式的变化,它是脆弱的,并且不能清楚地传达意图。我推荐弗里德尔的书来讨论这个话题。我应该把任何参数传递给preg_replace吗?甚至添加惰性字符似乎都不起作用。@Gremo我已经编辑了我的答案,我给你的模式(神秘地)不起作用,但是这一个会起作用。
preg\u replace('/([^\u]*)$/','3','a\u b\u c')
我得到了a\u\u 33
,它使替换加倍…@Gremo,抱歉,现在修复了。问题在于没有将限制
与preg_replace()
一起使用,因此它同时替换了c
和`````(在字符串末尾)。因此,您可以使用我将答案更改为的+
,或者在preg_replace()
中包含1
的限制。与真理解决方案相同的问题,preg_replace('/([^.]*)$/,'3','a__c')
得到了a_b_33
。啊,显然preg_replace默认为全局。因此,您需要使用[^ _]+或limit=1。因为@bfrohs更新了他的答案来做前者,所以我更新了我的答案来做后者。通过使用/\u[^\ u]+$/
,您可能会获得更好的性能,这意味着您还需要做“\u$replacement”
。嗯,不确定我为什么首先包括子模式。我在没有它的情况下重新运行,在最后一种情况下(0.5s),它确实提高了性能,但仍然不如strrpos
那么快。无论如何,我已经删除了子模式。
a_b_c:
usingExplode: 0.64s
usingStrrpos: 0.34s
usingPreg : 0.33s
abcdefghijklmnopqrstuvwxy_z:
usingExplode: 0.61s
usingStrrpos: 0.32s
usingPreg : 0.32s
a_bcdefghijklmnopqrstuvwxyz:
usingExplode: 0.60s
usingStrrpos: 0.32s
usingPreg : 0.32s
a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z:
usingExplode: 1.39s
usingStrrpos: 0.32s
usingPreg : 0.71s
a_b_c:
usingPreg2: 0.40s
abcdefghijklmnopqrstuvwxy_z:
usingPreg2: 1.91s
a_bcdefghijklmnopqrstuvwxyz:
usingPreg2: 0.38s
a_b_c_d_e_f_g_h_i_j_k_l_m_n_o_p_q_r_s_t_u_v_w_x_y_z:
usingPreg2: 1.04s
return preg_replace('/(.*_).*/', $replacement, $string);