用于PHP的正则表达式似乎很简单,但却让我感到害怕

时间:2013-11-20 07:41:53

标签: php regex

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

我有这个字符串:

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来完成这项工作(它变得像个人挑战)

感谢您的帮助!

5 个答案:

答案 0 :(得分:4)

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

让我们使用先行断言来解决这个问题:

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

以上匹配字符串或逗号的开头,然后检查 not 后面的内容是否与 keep 指定的两种表单中的一种匹配,并且鉴于此条件通过,匹配尽可能多的非逗号字符。

然而,这与@ anubhava的解决方案完全相同,这意味着它具有相同的弱点,因为在某些情况下它可以留下一个引导逗号。请参阅this Ideone demo

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

答案是肯定的。我们可以

preg_replace

分发交替,

'/(^|,)foo/'

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

'/^foo|,foo/'

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

foo

你有它。用'/^(foo),|,(?1)/' 代替它是什么,我们得到

foo

确实有效,如this second Ideone demo所示。


让我们花一些时间来简化你的表达。 '/^((?![09][0-9]{2}|[09][0-9][A-Za-z])[^,]*),|,(?1)/' 相当于[0-9],您可以通过添加\d来使用不区分大小写的匹配,如下所示:

/i

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

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

答案 1 :(得分:1)

尝试更多步骤:

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

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

答案 2 :(得分:1)

尝试匹配您想要保留的内容,然后使用逗号加入:

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

preg_replace所面临的问题是您必须删除的额外逗号,因为您不仅要删除aaa,还要删除aaa, 1}}或,aaa。现在什么时候你有东西要删除字符串的开头和结尾?你不能只说“我之前只删除逗号”,因为这可能会在字符串的开头产生额外的逗号,反之亦然。所以基本上,除非你想搞好前瞻和/或外观,你最好分两步完成。

答案 3 :(得分:1)

这应该适合你:

$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

答案 4 :(得分:0)

试试这个:

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

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

根据@GeoffreyBachelet的建议,要删除剩余的逗号,你应该这样做:

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