首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >POSIX正则表达式限制重复

POSIX正则表达式限制重复
EN

Stack Overflow用户
提问于 2011-04-18 06:00:35
回答 2查看 3.8K关注 0票数 1

我正在尝试grep,以获得输入字符串允许的最大重复次数,但似乎无法使其正常工作。

输入文件有三行,分别重复3、5和7次"pq“。>=3、>=5表达式运行良好,但“介于3和5之间”表达式{3,5}也显示了具有七次重复的行。

代码语言:javascript
复制
DEV /> cat input.txt
pq -- One occurance of pq
pqpqpqpqpq -five occurances of pq
pqpqpqpqpqpqpq -- seven occurances of pq


DEV /> grep "\(pq\)\{3,\}" input.txt
pqpqpqpqpq -five occurances of pq
pqpqpqpqpqpqpq -- seven occurances of pq


DEV /> grep "\(pq\)\{5\}" input.txt
pqpqpqpqpq -five occurances of pq
pqpqpqpqpqpqpq -- seven occurances of pq

DEV /> grep "\(pq\)\{3,5\}" input.txt
pqpqpqpqpq -five occurances of pq
pqpqpqpqpqpqpq -- seven occurances of pq

是我做错了什么,还是这是预期中的行为?

如果这是预期的行为(因为具有7个PQ的串具有3-5个PQ),

1)在什么情况下最大重复次数适用?{3,5}和{3,}(大于3)之间的差异是什么?

2)我可以用"^“锚定我的正则表达式,但是如果我的字符串不是以"pq”结尾并且有更多的文本怎么办?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-18 06:06:05

如果一条线有七个重复的东西,那么它也包含该东西的3-5个重复,并且在几个点上,不少于。

如果希望锚定匹配,请使用匹配锚点。否则,他们当然不是。

/X{3,}//X{3,5}/之间的实际区别在于它匹配字符串的长度-匹配的范围(或跨度)。如果您所寻找的只是一个布尔型的yes/no响应,并且您的模式中没有进一步的内容,那么这并没有太大的区别;事实上,如果一个相当聪明的正则表达式引擎知道这样做是安全的,那么它将提前返回。

查看差异的一种方法是使用GNU grep的-o‑‑only‐matching选项。观看:

代码语言:javascript
复制
$ echo 123456789 | egrep -o '[0-9]{3}'
123
456
789
$ echo 123456789 | egrep -o '[0-9]{3,}'
123456789
$ echo 123456789 | egrep -o '[0-9]{3,5}'
12345
6789
$ echo 123456789 | egrep -o '[0-9]{3,5}[2468]'
123456
$ echo 123456790 | egrep -o '[0-9]{3,5}[13579]'
12345
6789

为了理解最后两个是如何工作的,跟踪正则表达式引擎的尝试是很有用的,包括回溯步骤。您可以通过以下方式使用Perl完成此操作:

代码语言:javascript
复制
$ perl -Mre=debug -le 'print $& while 1234567890 =~ /\d{3,5}[13579]/g'
Compiling REx "\d{3,5}[13579]"
Final program:
   1: CURLY {3,5} (4)
   3:   DIGIT (0)
   4: ANYOF[13579][] (15)
  15: END (0)
stclass DIGIT minlen 4 
Matching REx "\d{3,5}[13579]" against "1234567890"
Matching stclass DIGIT against "1234567" (7 chars)
   0 <> <1234567890>         |  1:CURLY {3,5}(4)
                                  DIGIT can match 5 times out of 5...
   5 <12345> <67890>         |  4:  ANYOF[13579][](15)
                                    failed...
   4 <1234> <567890>         |  4:  ANYOF[13579][](15)
   5 <12345> <67890>         | 15:  END(0)
Match successful!
12345
Matching REx "\d{3,5}[13579]" against "67890"
Matching stclass DIGIT against "67" (2 chars)
   5 <12345> <67890>         |  1:CURLY {3,5}(4)
                                  DIGIT can match 5 times out of 5...
  10 <1234567890> <>         |  4:  ANYOF[13579][](15)
                                    failed...
   9 <123456789> <0>         |  4:  ANYOF[13579][](15)
                                    failed...
   8 <12345678> <90>         |  4:  ANYOF[13579][](15)
   9 <123456789> <0>         | 15:  END(0)
Match successful!
6789
Freeing REx: "\d{3,5}[13579]"

当你对比赛后的内容有额外的限制时,那么你选择哪种类型的重复可以产生很大的不同。在这里,我将对每个匹配的结束位置施加一个限制,即它需要在奇数位之前结束:

代码语言:javascript
复制
$ perl -le 'print $& while 1234567890 =~ /\d{3}(?=[13579])/g'
234
678
$ perl -le 'print $& while 1234567890 =~ /\d{3,5}(?=[13579])/g'
1234
5678
% perl -le 'print $& while 1234567890 =~ /\d{3,}(?=[13579])/g'
12345678

因此,当你有事情必须在之后发生时,它可以产生很大的不同。当你只是在决定整行是否与某项匹配时,它可能不那么重要。

票数 2
EN

Stack Overflow用户

发布于 2011-04-18 06:06:19

这是预期的行为。字符串“您可能希望尝试锚定您的正则表达式,如^\(pq\)\{3,5\}$

编辑以匹配已编辑的问题:

  1. 最大值适用于所有情况。现在的情况是,grep正在匹配重复出现的7次"pq“中的5次(最有可能是前5次),并且由于它找到了匹配项,所以它会打印出这一行。
  2. 您必须找到一种方法来更改正则表达式,以匹配您想要的内容,而不是您不想要的内容。例如,要匹配以3-5次重复的"pq”开头的行,您可以这样做:^\(pq\){3,5}\($|[^p]|p$|p[^q]\)。它匹配3-5个“pq”,后面紧跟行尾或除“p”或“p”之外的任何字符,后跟行尾或"p"-followed-by-any-character-other-than-"q".
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5696750

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档