PHP 的正则表达式看起来很简单,但正在杀死我


Regex for PHP seems simple but is killing me

我正在尝试用正则表达式替换字符串,我真的希望社区可以帮助我。

我有这个字符串:

031,02a,009,a,aaa,AZ,AZE,02B,975,135

我的目标是删除这个正则表达式的反面

[09][0-9]{2}|[09][0-9][A-Za-z]

a,aaa,AZ,AZE,135

(查看它的实际效果:http://regexr.com?3795f (

我的最终目标是preg_replace第一个字符串只得到

031,02a,009,02B,975

(查看它的实际效果:http://regexr.com?3795f (

对所有解决方案都持开放态度,但我承认,如果可能的话,我真的很喜欢用preg_replace来做这项工作(它变成了一个个人挑战(

感谢所有的帮助!

> 正如@Taemyr在评论中指出的那样,我以前的解决方案(使用后看断言(是不正确的,因为它一次会消耗 3 个字符,即使子字符串并不总是 3 个字符。

让我们使用一个前瞻断言来解决这个问题:

'/(^|,)(?![09][0-9]{2}|[09][0-9][A-Za-z])[^,]*/'

上面匹配字符串或逗号的开头,然后检查以下内容是否与您指定保留的两种形式之一不匹配,并且给定此条件通过,匹配尽可能多的非逗号字符。

但是,这与@anubhava的解决方案相同,这意味着它具有相同的弱点,因为在某些情况下它可以留下前导逗号。请参阅此 Ideone 演示。

ltrim逗号是去那里的干净方式,但话又说回来,如果你正在寻找"干净的去路",你不会尝试使用一个preg_replace开始,对吧?您的问题是是否可以在不使用任何其他 PHP 函数的情况下执行此操作。

安维尔是肯定的。我们可以采取

'/(^|,)foo/'

分配交替,

'/^foo|,foo/'

这样我们就可以附加我们希望仅在第一种情况下捕获的额外逗号,

'/^foo,|,foo/'

当我们用实际的正则表达式替换foo时,这将是一个毛茸茸的表达,不是吗。值得庆幸的是,PHP 支持递归模式,因此我们可以将上述内容重写为

'/^(foo),|,(?1)/'

你有它。用foo代替它是什么,我们得到

'/^((?![09][0-9]{2}|[09][0-9][A-Za-z])[^,]*),|,(?1)/'

这确实有效,如第二个 Ideone 演示所示。


不过,让我们花一些时间来简化您的表达式。 [0-9]等效于'd,可以通过添加/i来使用不区分大小写的匹配,如下所示:

'/^((?![09]'d{2}|[09]'d[a-z])[^,]*),|,(?1)/i'

您甚至可以压缩内部交替:

'/^((?![09]'d('d|[a-z]))[^,]*),|,(?1)/i'

尝试更多步骤:

$newList = array();
foreach (explode(',', $list) as $element) {
  if (!preg_match('/[09][0-9]{2}|[09][0-9][A-Za-z]/', $element) {
    $newList[] = $element;
  }
}
$list = implode(',', $newList);

你还有你的正则表达式,看!个人挑战已完成。

尝试匹配要保留的内容,然后用逗号连接它:

preg_match_all('/[09][0-9]{2}|[09][0-9][A-Za-z]/', $input, $matches);
$result = implode(',', $matches);

您将面临的问题是您必须删除额外的逗号preg_replace因为您不仅要删除aaa,实际上还想删除aaa,,aaa。现在,当您在字符串的开头和结尾都有要删除的内容时怎么办?你不能只说"我之前只去掉逗号",因为这可能会导致字符串开头出现一个额外的逗号,反之亦然。所以基本上,除非你想搞乱前瞻和/或后视,否则你最好分两步完成。

这应该适合您:

$s = '031,02a,009,a,aaa,AZ,AZE,02B,975,135';
echo ltrim(preg_replace('/(^|,)(?![09][0-9]{2}|[09][0-9][A-Za-z])[^,]+/', '', $s), ',');

输出:

031,02a,009,02B,975

试试这个:

preg_replace('/(^|,)[1-8a-z][^,]*/i', '', $string);

这将删除从字符串开头或逗号开始的所有子字符串,后跟不允许的第一个字符,直到但不包括下一个逗号。

根据@GeoffreyBachelet建议,要删除剩余逗号,您应该执行以下操作:

trim(preg_replace('/(^|,)[1-8a-z][^,]*/i', '', $string), ',');