我正在尝试grep输入字符串允许的最大重复次数,但似乎无法使其正常工作。
输入文件有三行,分别为3,5和7次重复的“pq”。 > = 3,> = 5表达式工作正常,但“3到5之间”表达式{3,5}也表示该行有七次重复。
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”结尾并且有更多文本会怎么样?
答案 0 :(得分:2)
如果一条线有七次重复的任何东西,那么它也包含3-5次重复的东西,并且在几个点上,不少于此。
如果您希望锚定匹配,请使用匹配锚点。否则,当然,他们不是。
/X{3,}/
和/X{3,5}/
之间的实际区别在于它匹配的字符串有多长 - 匹配的范围(或范围)。如果您正在寻找的是一个布尔的是/否响应,并且您的模式中没有任何其他内容,那么它并没有太大的区别;实际上,如果一个聪明的正则表达式引擎知道这样做是安全的,它将会提前返回。
查看区别的一种方法是使用GNU grep的 -o 或 - only-matching 选项。观看:
$ 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来做到这一点:
$ 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]"
如果您对比赛后的内容有其他限制,那么您选择的重复类型可以产生很大的不同。在这里,我将对允许每个匹配完成的位置施加约束,说它需要在奇数位之前结束:
$ 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
因此,当你有事情必须在事后发生时,它可以产生很大的不同。当你只是决定整行是否匹配时,它可能不那么重要。
答案 1 :(得分:1)
这是预期的行为。字符串“pqpqpqpqpqpqpq”实际上确实有三到五次重复的“pq”,然后还有一些更好的措施。您可能希望尝试锚定正则表达式,例如^\(pq\)\{3,5\}$
。
编辑以匹配已修改的问题:
^\(pq\){3,5}\($|[^p]|p$|p[^q]\)
。这匹配3-5“pq”,紧接着是行尾或任何字符 - 除了“p”或“p” - 后续行或“p” - 后续行为 - 通过任何字符的-另一不包括─ “q”。