3

我知道我在这里做了一些愚蠢的事情,但是在我的 Unix/Linux 课程中给我们的正则表达式备忘单暗示(通过我的阅读)这应该在包含年份的文本文件中找到行(数字从 0000 到 9999):

grep \d{4} file.txt

为什么它什么也没找到呢?这是使用 bash,在 Windows 上的 PuTTY 和 Mac 上的终端上具有相同的结果。我尝试了括号和引号的变体,但没有效果。搜索[0-9][0-9][0-9][0-9]工作,但没有\d{4}似乎没有我所期望的功能。

在相关说明中,为什么会.\+产生我期望的效果.+,而.+只是“不起作用”?(我知道它告诉 grep 寻找一些东西,但我不知道是什么。)也就是说,这似乎是要求“这里有一个或多个字符”而不是“一个字符后跟加号”的方式。(这是做作业的正确方法,老师可以向我解释为什么会这样)以及如何搜索“一个字符后跟加号”?

4

3 回答 3

3

您的备忘单可能会声明这\d{4}是一个有效的正则表达式,意思是“四位数”;它可能会声明grep在文件中搜索正则表达式。分开来看,这两种说法都是正确的。但总的来说,它们具有高度误导性,因为grep PATTERN FILE期望一种正则表达式(POSIX“基本正则表达式”,BREs),而\dand{4}是来自不同类型正则表达式的符号(有时称为“Perl Compatible Regular Expressions”,PCREs ,在 Perl 编程语言之后)。

许多版本都grep支持一个-P标志来指示该模式是 PCRE 而不是 BRE;你可以试试:

grep -P '\d{4}' file.txt

(注意 . 周围的单引号\d{4}。这些是必要的,因为否则 Bash 将\d作为 的一种简写'd',因此传递给的实际模式grep将是d{4},意思是“四个d”而不是“四个数字”。或者,您可以write grep -P \\d{4} file.txt,它以不同的方式解决了相同的问题。)


编辑添加:对不起,我未能涵盖您问题的第二部分,关于+. 因此,根据相关规范,1

grep .+ file.txt

用于.表示“除 NUL 之外的任何字符”并+表示“实际的加号”。所以它真的应该打印file.txt包含非初始加号的行;如果您看到不同的行为,那么您的外壳和/或grep必须是不合格的。

此外,这:

grep .\+ file.txt

与上述相同,因为符合 POSIX 的 shell(例如 Bash)将\+视为一种奇特的编写方式+,因此grep将看到与以前相同的参数。(grep将无法知道您输入的.\+是不是.+.)

最后,这个:

grep '.\+' file.txt

\实际传递到 的地方grep)具有未定义的行为:给定的grep实现可以将其.+视为\+与给出错误信息。碰巧的是,GNU 实现采用“一种或多种”解释,但其他可能不同。

脚注:

  1. 规范grep以及BRE 和 ERE 规范grep规范链接和引用)。同样相关的是shell 规范,因为它是 shell 决定传递给的实际参数grep
于 2013-05-16T23:47:37.620 回答
2

如果您的版本grep碰巧不支持-P,以下将起作用:

grep "\d\{4\}" file.txt

至于您的其他问题,使用相同风格的正则表达式,.+将匹配任何后跟+符号的字符。 .\+将匹配一个或多个任意字符。

于 2013-05-16T23:55:46.740 回答
2

默认情况下,grep 使用 POSIX 正则表达式风格,它不包括\d. 要使用您的表达式,您需要切换到 PCRE (arg -P)

grep -P \\d{4} file.txt 

这将返回 file.txt 中 4 位字符串的每个实例。

于 2013-05-16T23:46:57.527 回答