Perl Regex替代问题

时间:2013-08-29 19:24:52

标签: regex perl

我正在尝试使用正则表达式从分号分隔的字符串中删除标记。示例字符串如下所示:

Field1=Blah;Field2=Bluh;Field3=Dingdong;Uid=John;Pwd=secret;Field4=lalali Field1=Blah;Field2=Bluh;Field3=Dingdong;Uid=John;Pwd=secret;Field4=lalali;

所以我想在单独的命令中删除“Uid”和“Pwd”标记,以便不删除任何尾随标记(例如,Field4应保留在结尾)。

我目前的尝试是:

$mystring =~s /Uid=.+;//i;

产生

Field1=Blah;Field2=Bluh;Field3=Dingdong;Field4=lalali

哪个适用于第一行,但不适用于第二行,最后是分号,产生

Field1=Blah;Field2=Bluh;Field3=Dingdong;

并错误地删除了Field4。我试过了很多变种,比如

$mystring =~s /Uid=.+;?//i; $mystring =~s /Uid=.+;+?//i;

没有成功。我意识到我需要告诉正则表达式只匹配第一个分号,但我无法弄清楚如何。

现在,只是为了让我看起来并不完全愚蠢,我能够通过这样做得到它:

$mystring =~s /Uid=[^;]+;//i;

但是我仍然想知道为什么我不能说这个表达只匹配第一个分号......

2 个答案:

答案 0 :(得分:4)

当您使用+*等量词时,他们会贪婪。他们吞噬了尽可能多的角色,只有在他们被迫回溯时才会回馈他们。因此,模式.*;将匹配所有内容,直到 last 分号。

也许贪婪的量词应该节食。我们可以使用惰性版本强制它们:+?*?。这些将尽早终止。所以模式是:

/Uid=.+?;/  # repeat for Pwd

匹配到第一个分号

这样可行,但是使用带有.类的非贪婪量词而不是使用否定字符类被认为是好的风格:

/Uid=[^;]+;/

因为这样做的方法可能会更少(比如删除其余部分)。它也比其他解决方案更明确。

答案 1 :(得分:3)

如果您不想使用否定字符类(适用于大多数正则表达式包),您可以使用非贪心量词来匹配关键字后面的数据(但它只适用于Perl兼容的regex包)。有关详细信息,请参阅Regular expressions下的量词。

$mystring =~s /Uid=.+?;//i;

额外的问号使+非贪婪;它需要匹配的最小字符串而不是最大值,因此它不会匹配任何分号。