我试图在我的主目录中列出一些隐藏文件,并且grep
在与ls
command结合时遇到了一个非常奇怪的command行为。
ls -a
在我的主目录上执行并按预期获得了包括隐藏文件在内的所有文件。ls -a |grep -i .xau*
它,它也按预期工作。ls -a |grep -i .x*
在同一个目录中执行,但它根本没有列出任何内容。ls -a |grep -i .*x
(注意这次通配符 * 和字符 'x' 交换了位置),有趣的是它的行为与我在第 3 步中的意图相似。我试图用这个命令同样的事情ls -a .*x
,并ls -a .*X
但我得到没有这样的文件或目录错误。你们中的一些人可能会问为什么不只是使用,ls -a .x*
而是使用grep
适当的颜色打印。所以有人可以向我解释一下吗?
您正在遭受过早的全球扩张。
.xa*
不会扩展,因为它与当前目录中的任何内容都不匹配。(Glob 区分大小写。)但是,.x*
确实匹配了一些文件,因此在grep
看到它之前它会被 shell 扩展。
当grep
接收到多个参数时,它假定第一个是模式,其余的是用于搜索该模式的文件。
因此,在命令中ls -a | grep -i .x*
, 的输出ls
被忽略,并在文件“.xsession-errors.old”中搜索模式“.xsession-errors”。不出所料,什么也没找到。
为了防止这种情况,请将您的特殊字符放在单引号或双引号内。例如:
ls -a | grep -i '.x*'
Run Code Online (Sandbox Code Playgroud)
您还患有正则表达式与全局混淆。
您似乎正在寻找以文字字符串“.x”开头并后跟任何内容的文件,但正则表达式的工作方式与文件 glob 不同。的*
在正则表达式的意思是“前面的字符0次或更多次”,而不是因为它在文件水珠“的任何字符的序列”。所以你可能想要的是:
ls -a | grep -i '^\.x'
Run Code Online (Sandbox Code Playgroud)
这将搜索名称以文字字符“.x”或“.X”开头的文件。实际上,由于您只指定了一个字母,因此您可以轻松地使用字符类而不是-i
:
ls -a | grep '^\.[xX]'
Run Code Online (Sandbox Code Playgroud)
关键是正则表达式与文件全局非常不同。
如果您只是ls -a | grep -i '.x*'
按照建议的那样尝试,您会很惊讶地看到每个文件都将显示出来!(与ls -a
直接输出相同,除了像在ls -a -1
.
怎么来的?
好吧,在正则表达式中(但不是在 shell glob 中),句点 ( .
) 表示“任何单个字符”。星号 ( *
) 表示“零个或多个前面的字符”。所以正则表达式的.x*
意思是“任何字符,后跟零个或多个字符‘x’的实例”。
当然,不允许有空文件名,因此每个文件名都包含“一个字符后跟至少零个‘x’”。:)
概括:
要得到你想要的结果,你需要明白两件事:
*
,?
,[]
和其他一些人)将得到扩展的shell,再也不运行此命令之前看到他们,