BASH正则表达式{}混乱

时间:2013-08-14 20:56:32

标签: regex bash

我认为我对{3,5}部分如何运作有错误的想法。

根据我的理解,它指定数字必须符合的范围才能返回搜索结果?

例如,3,5表示返回搜索的3-5位数字。经过一些实验,我意识到我的逻辑并不完全正确。

它似乎适用于3-5个字符,然后是8,9和10个字符。

我在这里错过了一个模式吗?或者更简单地说,有人可以向我解释背后的逻辑吗?它只是3或5的倍数?包括3-5的范围?这里真的很困惑。谢谢!

  

用户@矩阵:〜> echo 1234567891234 | grep'[0-9] {3,5}'

     

1234567891234

以上匹配成功,包含12个字符......

4 个答案:

答案 0 :(得分:2)

您可以使用-o选项直观显示grep的工作原理:

echo 1234567891234 | grep -o '[0-9]\{3,5\}'

输出:

12345
67891
234

-o将在每次匹配后添加一个新行以输出。如果没有该选项,grep将只打印匹配发生的整行 - 再次输入字符串本身是什么。这样你就无法看到grep如何与字符串完全匹配。

但是现在你可以看到grep在该行中发现了多次匹配2次5位数字符串和1次3位数字符串。

除非您使用{}选项,否则在-E括号前需要斜线。

答案 1 :(得分:2)

你假设{3,5}定义了在其前面的类中选择的字符的重复 - 在3到5(包括两个端点)之间重复,这是正确的。 您也可以执行类似{3,}的操作,这意味着 - “至少3次”

使用-Ex选项E - 这样您就不必在括号和x之前使用斜杠来整理整行:

[alfasin@otrs ~]$ echo 1234567891234 | grep -Ex '[0-9]{3,5}'
[alfasin@otrs ~]$ echo 1234567891234 | grep -Ex '[0-9]{3,13}'
1234567891234

从grep手册:

  

-E, - extended-regexp                 将PATTERN解释为扩展正则表达式(ERE,见下文)。 (-E由POSIX指定。)

     

-x, - line-regexp                 仅选择与整行完全匹配的匹配项。 (-x由POSIX指定。)

答案 2 :(得分:2)

它的工作方式与您编写完全相同:

grep '[0-9]\{3,5\}'  - Is there 3 to 5 sequential numeric characters in this string?

如果字符串是1234567891234,那里有一个包含3-5个数字字符的子字符串。

如果您只对仅包含3-5个数字字符且不超过5个字符的字符串感兴趣,则必须在正则表达式中添加一些边界。您还应该使用-E标志,该标志使用更现代版本的正则表达式:

$ echo 12345678901234 | grep -E "(^|[^0-9])[0-9]{3,5}([^0-9]|$)"

这不会打印任何内容,但这会:

$ echo 1234 | grep -E "(^|[^0-9])[0-9]{3,5}([^0-9]|$)"

而且:

$ echo 12345aaa6789aaa01234 | grep -E "(^|[^0-9])[0-9]{3,5}([^0-9]|$)"

第一个(^|[^0-9])在行的开头(那是领先的^),或除了字符0-9之外的任何内容 >。 (那是[^0-9])。在扩展正则表达式中使用(...|...)意味着左侧的表达式或右侧的表达式。对于结尾([^0-9]|$)也是如此,它表示非数字或行的结尾。

中间是你的[0-9]{3,5}(扩展表达式不需要反斜杠)。这表示3至5位数字。并且,由于它在任何一侧都被非数字或字符串的开头或结尾绑定,这将完成你想要的。

有几件事:

$ echo 12345aaa6789aaa01234 | grep -E "(^|[^0-9])[0-9]{3,5}([^0-9]|$)"

$ grep -E "(^|[^0-9])[0-9]{3,5}([^0-9]|$)" <<<"12345aaa6789aaa01234"

意思是几乎相同的东西。但是,第二个更有效,因为只需要运行一个进程,并且没有管道。另外,打字时间更短。

此外,您可以使用(并且首选使用)字符类:

$ grep -E“(^ | [^ [[:digit:]])[[:digit:]] {3,5}([^ [:digit:]] | $)”&lt;&lt; &LT; “12345aaa6789aaa01234”

即使您不在使用拉丁字母数字字符的地方,也可以使您的正则表达式正常工作。这是一种较短的方法,因为\d[:digit:]属于同一类:

$ grep -E "(^|[^\d])\d{3,5}([^\d]|$)"<<<"12345aaa6789aaa01234"

答案 3 :(得分:1)

当您使用该特定正则表达式时,它匹配输入字符串中的前5个字符(有关可视化,请参阅http://regexpal.com/?flags=g&regex=[0-9]{3%2C5}&input=1234567891234%0A)。一旦grep找到匹配项,它就会停止处理并返回匹配的行。它甚至没有注意到那场比赛以外的任何事情。

如果您正在寻找仅匹配完全 3-5位数的孤立序列的内容,请尝试使用以下正则表达式:

\b[0-9]{3,5}\b

'\b'将匹配单词边界,意味着单词字符(字母,数字等)和非单词字符(空格,标点符号等)之间的过渡。这会为1234生成匹配,但不会生成121234567891234

您还可以使用lookaround作为一种更强大的方法,以确保您的匹配在其之前和之后没有数字。但是,grep对环视的支持似乎并不完整,所以你可能不得不使用像perl这样的东西。