组 grep 命令

组 grep 命令

我想要grep不以 开头s且包含m.

我尝试了这个有效的解决方案:

ls | grep -Ev "^s" | grep "m"

但是当我尝试使用单个grep命令执行此操作时,它失败了:

ls | grep -E '^[^s]*m*'

我无法解释为什么。是否可以只用一条命令来完成grep

答案1

你不需要grep这个。

printf '%s\n' [!s]*m*

测试:

$ touch small big larger enormous much
$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 big
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 enormous
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 larger
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 much
-rw-r--r--  1 kk  wheel  0 Oct 24 13:20 small
$ printf '%s\n' [!s]*m*
enormous

文件名通配模式[!s]*m*扩展到所有不以 开头s但包含m.

然而,这将找不到m仅包含第一个字符的文件名。

为此,您可以分别查找不以m或开头s但包含m, 开头的文件以及以 , 开头的文件m。维护起来有点麻烦,并且通过阅读代码并不能立即清楚它的作用:

$ printf '%s\n' [!ms]*m* m*
enormous
much

或者,使用find,恕我直言,更容易阅读:

$ find . -maxdepth 1 -name '[!s]*' -name '*m*'
./enormous
./much

答案2

*我认为您在正则表达式中使用了不正确的内容。

该规范(也参见 grep 的手册页)指出

*      The preceding item will be matched zero or more times.

因此,您的正则表达式意味着:“匹配以字母 以外的任何内容开头的任何文件名s,然后匹配零次或多次,然后匹配字母零次或多次m。”

正则表达式应该改为

ls | grep -E '^[^s][[:alnum:]]*m'

即你必须指出什么符号应该在“m”之前出现零次或多次,在您的情况下,任何字母数字字符都应该可以。如果您的文件名可以包含-_,则替换[[:alnum:]][[:print:]].

作为一个极端的情况,如果你的文件名也可以开始使用 an 时m,正则表达式将是

ls | grep -E '(^m|^[^s][[:print:]]*m)'

答案3

首先,您不应该解析ls.除此之外,我将回答您关于 的问题grep

如果你坚持使用grep那么你想要的是这样的:

grep -E "^[a-rt-zA-RT-Z][[:alnum:]]*m" file

事实上,它甚至可以在没有以下内容的情况下工作-E

grep "^[a-rt-zA-RT-Z][[:alnum:]]*m" file 

s这将打印以或以外的任何内容开头的任何内容,S然后是包含 的任何字母数字字符m,以及之后的任何字符,无论它们是否是m。实际上,它给出了您正在寻找的输出。

当您处理文件时,printf上面的第一个解决方案要好得多,因为它不需要解析ls.您可以将grep上述内容与文件名一起使用,但我建议不要这样做,并建议将其与标准输出中的文件内容或数据一起使用。

您还可以用于find文件,因为它不需要解析:

find /path/to/directory -type f -name "*m*" -name "[!s]*"

根据您的环境,您可能需要逃避*

find /path/to directory -type f -name "\*m\*" -name "'[!s]\*"

相关内容