我想要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]\*"