使用 grep 和 * 时有困惑吗?

使用 grep 和 * 时有困惑吗?

最近,我与一位同事交谈时,他正处于自我封闭状态,这时我发现他做了类似的事情ls -l | grep asdf*

我问他:“为什么弄得一团糟?”他回答说:“我一向都是这么做的。”

我并没有立即发现任何问题,但仍然感觉不对劲。当我后来亲自尝试时,我看到了不同的行为:

--> ls -l | grep ls
-rwxr-xr-x 1 root root   22896 Nov 19  2012 false
-rwxr-xr-x 1 root root  105840 Nov 19  2012 ls
-rwxr-xr-x 1 root root   44640 Nov 19  2012 lsblk
-rwxr-xr-x 1 root root    6272 Nov 19  2012 lsmod
-rwxr-xr-x 1 root root   31912 Nov 19  2012 ntfsls

--> ls -l | grep ls*
Binary file lsblk matches
Binary file lsmod matches

这里到底发生了什么?我认为最糟糕的情况是,grep 会将其视为正则表达式l(s*)并返回所有出现的l,但这个输入甚至没有出现在 ls 中!(我从 运行它/bin)。

当您在搜索字符串后添加一个 glob 时,grep 会做什么?我是否应该告诉我的同事以后不要再这样做?

答案1

当你这样做时grep ls*首先扩展ls*为当前目录中匹配的文件列表,因此命令变为

ls -l | grep ls lsblk lsmod

在这种情况下,grep将忽略标准输入并将第一个参数ls视为要匹配的模式里面文件lsblklsmod,就像您输入的那样grep ls lsblk lsmod(大概在/bin):

$ grep ls lsblk lsmod
Binary file lsblk matches
Binary file lsmod matches

另一方面,如果当前目录中没有 glob 匹配,并且nullglob未设置 shell 的选项,ls*则将保留联合国展开,以便grep查看ls*并匹配任何文件名称匹配l后跟零个或多个s字符(基本上是任何带有 的文件名l)例如:

$ pwd
/home/steeldriver
$ echo ls*
ls*

ls*(我的主目录中没有与 shell glob 匹配的文件);然后

$ ls /bin | grep 'ls*'
bzless
chacl
false
.
.
.
zless

不要这么做

答案2

为了更加安全,您的同事应该使用:

ls -l | grep "asdf*"

处理管道输出,使用引号我们跳过 shell 文件扩展,所以我们说查找后跟asd零个或多个 的行f,更好的用例是:

ls -l | grep "asdf.*"

另一件需要提及的事情是,如果当前目录中没有任何文件与该模式匹配,它将被视为原样grep,大多数情况下都是如此。

另请注意,解析ls输出是这不是一件好事

相关内容