为什么“ grep * ”不起作用?

为什么“ grep * ”不起作用?

在学习linux的这几天,我发现一个让我困惑的事情:

$ cat abcd
line One
line Two
line Three
$ cat abcd | grep *
$ _                       //nothing greped
$ cat abcd | grep ""
line One
line Two
line Three
$ cat abcd | grep "*"
$ _                       //nothing greped

“_” 只是光标,不要误会:)

谁能解释一下?谢谢

答案1

shell 将glob*扩展为当前目录中所有(非点)文件的字母列表。 的参数grep是搜索表达式和文件列表。 因此grep *最终使用第一个文件名作为搜索表达式。 您正在其他文件中查找第一个文件的名称(作为正则表达式)。

仅当您未提供任何显式文件名时,Grep 才会搜索标准输入。请参阅:

echo moo | grep . /etc/issue
Handmade Linux for OS/X v 0.001

顺便说一句,*不是一个有效的正则表达式。正如您所发现的,空搜索表达式匹配所有输入行。匹配所有非空输入行的正则表达式是.;在正则表达式中,点是一个元字符,它匹配一个字符,除换行符之外的任何字符。 kleene 星号是一个后缀运算符,它允许零次或多次重复上一个正则表达式,因此您经常会看到.*“任何东西”的正则表达式,但在这种情况下,它是多余的,因为您已经用空搜索字符串匹配了任何东西。

最后,将单个文件保存为单个文件被认为是不好的形式cat。您不必cat file | grep ""保存一个进程,也许还有一些轻蔑通过grep直接读取文件;grep "" file

答案2

将对grep *当前目录中的文件进行“全局”扩展。

我无法准确预测会发生什么,但*肯定会与文件名匹配abcd。因此,您最终可能会在abcd文件中搜索“abcd”。或者,您可能最终会在其他文件中搜索(按字典顺序)第一个文件的名称。

如果当前目录为空,您最终会搜索*。但这也不起作用,因为第一个命令行参数是正则表达式,而“*”不是有效的正则表达式。

为了防止通配符,请这样写:

$ cat abcd | grep "*"

...但根据上述原因,这没有任何意义。

要搜索文字“*”字符:

$ cat abcd | grep "\\*"

答案3

在看到命令行参数之前grep,该参数由 shell 解析。对于 shell 来说,*是“当前目录中所有非点文件”的通配符。由于 shell 首先处理该参数,因此您的行将变成这样:

cat abcd | grep abcd otherfile zfile

(假设这三个文件位于您当前的目录中)。这就是grep可以看到其参数的内容,但这不是您想要的。

相反,你可以把模式放在grep引号中,这样它就是不是由 shell 处理:

cat abcd | grep "*"

这样更好,但仍然不是您想要的:grep使用正则表达式,而不是 shell 样式的通配符。星号grep表示“0..n 次重复前一个字符” - 您未指定的字符。接近,但还不够。

如果你想要一个“任意”模式,你正在寻找“0..n 次重复的随意的字符”。后者'.'在正则表达式中用句点 ( ) 表示:

cat abcd | grep ".*"

正是您所寻找的。

编辑:另一种情况更容易解释。如果grep ""你正在寻找一个空的字符串,它作为子字符串存在于任何字符串中。

答案4

Bash 总是将 * 解析为目录中文件的通配符占位符。在您的命令中,bash 将其理解为

cat abcd | grep abcd file1 file2 ...

因此它只显示空输出,因为它不是您要搜索的内容

相关内容