Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP preg_替换最后一个下划线之后出现的任何文本_Php_Regex_Preg Replace_Preg Match - Fatal编程技术网

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);