为什么通配符放在 grep 短语开头或结尾时的工作方式不同?

为什么通配符放在 grep 短语开头或结尾时的工作方式不同?

例如,我想计算当前目录中有多少文件具有特定扩展名。

我用了:

ls | grep ".txt" | wc -l

这有效,也有效:

ls | grep ".txt*" | wc -l

但为什么这也不起作用呢?

ls | grep "*.txt" | wc -l

为什么当我在扩展名之前使用通配符时,它在 grep 表达式中似乎不起作用?为什么它在最后没有效果(所有 txt 文件都以 .txt 结尾,所以我猜如果它是某种东西,它就不起作用像.txt.zip)?

答案1

$ ls *.txt

该命令将使用 shell 通配列出所有名称以.txt.

$ ls | grep "*.txt"

此命令将列出当前工作目录中的所有(非隐藏)文件,并将该输出发送到grep,这将根据正则表达式匹配文件名/*.txt/

/*.txt/

该正则表达式可能(取决于正在使用的正则表达式的风格)匹配以下模式:

*    -- zero or more characters of any type (or possibly only a literal '*'), followed by
.    -- exactly one character of any type, followed by 
txt  -- the literal string 'txt', followed by anything

在正则表达式中,*是一个通配符,代表“零个或多个前面的子表达式”;但它的工作方式与 shell glob 通配符不同。相关地,.不是句点;它是一个字符的通配符(类似于?shell glob 中的通配符)。因此,这个表达式将(再次取决于正则表达式的风格)匹配file.txtsometxtfile、中的任何一个photo_of_a_txt_file.png,但实际上不匹配txtfile(因为 之前的一个字符不匹配txt)。因此,重要的是要知道,文字字符串txt可以出现在除使用此正则表达式的文件名开头之外的任何位置。

捕获以以下结尾的文件名的更好的正则表达式.txt/\.txt$/

\.  -- A literal .
txt -- The literal string 'txt'
$   -- End of input

因此,如果你坚持管道ls进入grep(暂时不要进入那些可以写为什么解析 的输出ls是一个坏主意的书),你可能打算这样做:

$ ls | grep "\.txt$"

至于然后使用wc,你不需要这样做。 grep可以数:

$ ls | grep -c "\.txt$"

相关内容