正则表达式:{n}和{n,m}忽略最大重复次数

时间:2018-05-23 19:05:55

标签: regex grep

我对正则表达式的最大重复次数有疑问:{n}和{n,m}。

$ man grep
...
Repetition
    A regular expression may be followed by one of several repetition operators:
...
    {n}    The preceding item is matched exactly n times.
    {n,}   The preceding item is matched n or more times.
    {,m}   The preceding item is matched at most m times.  This is a GNU extension.
    {n,m}  The preceding item is matched at least n times, but not more than m times.
...

现在考虑一个测试文件:

$ cat ./sample.txt
1
12
123
1234

然后grep它为[0-9](数字)重复2次:

$ grep "[0-9]\{2\}" ./sample.txt
12
123
1234

?为什么这包括123和1234?

另外,我为同一个文本文件grep重复至少2次但不超过3次的数字:

$ grep "[0-9]\{2,3\}" ./sample.txt
12
123
1234

???为什么这会返回“1234”?

一个明显的解决方法是使用grep和reverse-grep来过滤掉过多的结果。例如,

$ grep "[0-9]\{2,\}" ./sample.txt | grep -v "[0-9]\{4,\}"
12
123

任何人都可以帮助我理解为什么{n}返回包含重复n次的模式的行?为什么{n,m}返回重复m次的模式?

2 个答案:

答案 0 :(得分:4)

除非您锚定正则表达式,否则它们可以匹配字符串中的任何位置。

$ grep "[0-9]\{2\}" ./sample.txt将匹配包含2位数的任何行。

使用^强制表达式从行的开头开始,$强制表达式与行尾相匹配。例如

$ grep '^[0-9]\{2\}$' ./sample.txt
# Using single quotes to avoid potential substitution issues. Hat tip to @ghoti

这应该只返回12

答案 1 :(得分:1)

可以在较长的文本中找到模式,也可以遵循相同的模式。对于grep,使用-o选项查看正则表达式找到匹配的位置。在由两位数字组成的数字中,或者在一个长度为10位的数字中,可以找到两位数字。

另一个答案指向两个锚,但有一个单词边界标记\b与边界位置匹配(如果使用)。这关闭了两端。不幸的是POSIX BRE(grep默认的正则表达式风格)并不支持这个,但在GNU sed中你可以启用Perl正则表达式并测试它:

grep -P '\b[0-9]{2}\b' file

只有grep两个\<\>匹配相同的位置:

grep '\<[0-9]\{2\}\>' file
相关问题