带 ls -a 的 grep 命令无法正常工作?

带 ls -a 的 grep 命令无法正常工作?

我试图列出我的主目录中的一些隐藏文件,并且grep在与命令结合时遇到了非常奇怪的命令行为ls

  1. ls -a在我的主目录上执行并按预期获取了所有文件,包括隐藏文件。
  2. 我想列出所有隐藏文件从“xau”开始,所以我执行了ls -a |grep -i .xau*并且它也按预期工作。
  3. 然后我ls -a |grep -i .x*在同一目录中执行但是它根本没有列出任何内容
  4. 然后我错误地输入了ls -a |grep -i .*x (请注意,这次通配符 * 和字符 'x' 交换了位置)有趣的是,它的表现与我在步骤 3 中的预期一致。我用这个命令尝试了同样的事情ls -a .*xls -a .*X但我得到了没有这样的文件或目录错误。

在此输入图像描述

在此输入图像描述

我已经添加了实际的文本输出这里。

你们中的一些人可能会问为什么不直接使用,ls -a .x*grep它可以打印出适当的颜色。那么有人可以向我解释一下吗?

答案1

你正在遭受过早的全球扩张。

.xa*不会展开,因为它与当前目录中的任何内容都不匹配。 (Glob 区分大小写。)但是,.x* 匹配某些文件,因此 shell 在grep看到它之前会对其进行扩展。

grep接收多个参数时,它假定第一个参数是模式,其余参数是用于搜索该模式的文件。

因此,在命令 中ls -a | grep -i .x*, 的输出ls被忽略,并在文件“.xsession-errors.old”中搜索模式“.xsession-errors”。毫不奇怪,什么也没发现。

为了防止这种情况,请将特殊字符放在单引号或双引号内。例如:

ls -a | grep -i '.x*'

你也正遭受着正则表达式与 glob 的混淆。

您似乎正在寻找以文字字符串“.x”开头且后跟任何内容的文件,但正则表达式的工作方式与文件通配符不同。这* 在正则表达式中表示“前面的字符零次或多次”,而不是像文件 glob 中那样的“任何字符序列”。那你又怎样大概想要的是:

ls -a | grep -i '^\.x'

这会搜索其名称的文件开始带有文字字符“.x”或“.X”。实际上,由于您只指定一个字母,因此您可以轻松地使用字符类而不是-i

ls -a | grep '^\.[xX]'

重点是正则表达式与文件 glob 有很大不同。

如果您ls -a | grep -i '.x*'按照建议尝试,您会非常惊讶地发现每个文件都会显示! (与直接输出相同ls -a,只是像 中那样放在单独的行上ls -a -1。)

怎么会?

嗯,在正则表达式(但不是在 shell glob 中),句点 ( .) 表示“任何单个字符”。星号 ( *) 表示“零个或多个前面的字符”。因此,正则表达式的.x*意思是“任何字符,后跟零个或多个字符‘x’的实例”。

当然,你不允许有空文件名,所以每一个文件名包含“一个字符后跟至少零个‘x’”。 :)


概括:

为了获得您想要的结果,您需要了解两件事:

  1. 不带引号的特殊全局字符(包括*?[]其他一些字符)将被扩展通过外壳在您运行的命令之前看到他们与
  2. 正则表达式与文件 glob 不同(并且更强大)。

答案2

问题是您没有*用引号引起来并让 shell 在运行命令之前展开它。看:

$ touch .xau1 .xau2
# this won't work
$ ls -a | grep -i .xau*
# but this does
$ ls -a | grep -i ".xau*"
.xau1
.xau2
# this one too
$ ls -a | grep -i '.xau*'
.xau1
.xau2
# check what shell sees
$ ls -a | grep -i .xau* # now don't press enter but C-x * and you'll see this:
$ ls -a | grep -i .xau1 .xau2

相关内容