如何使用preg_replace追加或替换尾随问号?

时间:2010-07-20 08:28:08

标签: php regex preg-replace

我想在字符串和字符串处强制执行单个问号。在JavaScript中它完美地运作:

var re = /[?7!1]*$/;
document.write('lolwut'.replace(re, '?'));
document.write('lolwut?'.replace(re, '?'));
document.write('lolwut??'.replace(re, '?'));
document.write('lolwut???'.replace(re, '?'));
document.write('lolwut???!!!11'.replace(re, '?'));

所有返回的值等于“lolwut?” PHP变体不能顺利运行:

$re = '/[?7!1]*$/';
echo preg_replace($re, '?', 'lolwut') . "\n";
echo preg_replace($re, '?', 'lolwut?') . "\n";
echo preg_replace($re, '?', 'lolwut??') . "\n";
echo preg_replace($re, '?', 'lolwut???') . "\n";
echo preg_replace($re, '?', 'lolwut???!!!11') . "\n";

输出是:

lolwut?
lolwut??
lolwut??
lolwut??
lolwut??

我在这里做错了什么?


更新

  

$(美元)断言字符串的结尾
  断言是对当前匹配点之后或之前的字符的测试,实际上不消耗任何字符

这里是我的困惑,以及preg_replace的隐含全局标志,感谢 salathe 提供线索。 (你们应该投票给他们的答案,真的)

3 个答案:

答案 0 :(得分:7)

结帐rtrim() - http://php.net/manual/en/function.rtrim.php

echo rtrim('lolwut','?7!1').'?'; // lolwut?
echo rtrim('lolwut?','?7!1').'?'; // lolwut?
echo rtrim('lolwut??','?7!1').'?'; // lolwut?
echo rtrim('lolwut???!!!11','?7!1').'?'; // lolwut?
echo rtrim('lolwut1??!7!11','?7!1').'?'; // lolwut?

rtrim将Strip whitespace (or other characters) from the end of a string

第二个论点:

  

您还可以通过charlist参数指定要删除的字符。只需列出要删除的所有字符。使用..,您可以指定一系列字符。

答案 1 :(得分:4)

只是回答问题(“我在这里做错了什么?”),你对正则表达式匹配的精确感到困惑。使用字符串,禁止第一个,正则表达式实际匹配两次这就是为什么你得到两个问号(两个匹配,两个替换)。这种行为的根源是量词的混合(*允许不匹配)和结束锚($匹配字符串的结尾)。

lolwut???!!!11

  • 正则表达式首先匹配???!!!11,这是您所期望的
  • 为字符串赋予lulwut?
  • 的新值
  • 然后它也匹配新字符串
  • 末尾的点
  • 导致lulwut??
  • 的最终替换值

如果您想继续使用与preg_replace相同的正则表达式,则只需将1的值提供给第四个($limit)参数,即可将其限制为一个替换:

preg_replace('/[?7!1]*$/', '?', 'lolwut???!!!111', 1);
// limit to only one replacement ------------------^ 

至于其他人所说的更好的解决方案,请使用rtrim

答案 2 :(得分:1)

你应该使用修剪功能:

echo trim('lolwut???!!!11', '?7!1');

输出是:

lolwut