Bash正则表达式:如何使用'grep'或'ls'匹配n次?

7

我希望用grepls按以下方式匹配n个数字:

echo "ABCD150915.7z" | grep "ABCD[[:digit:]]{6}.7z"

上述方法不起作用,我已经尝试了很多种方法...怎么办呢?
我知道还有其他方法,但请注意,我想知道是否可以使用grepls实现[[:digit:]]{6}
4个回答

16

是的,使用以下两种方法之一即可:

echo "ABCD150915.7z" | grep -E "ABCD[[:digit:]]{6}.7z"

启用带有-E的扩展正则表达式模式意味着花括号被理解。

或者,您可以转义花括号:

echo "ABCD150915.7z" | grep "ABCD[[:digit:]]\{6\}.7z"
如果您想列出与模式匹配的所有文件,则可以使用全局扩展(glob expansion):
ls ABCD[0-9][0-9][0-9][0-9][0-9][0-9].7z

...如果您正在考虑循环遍历这些文件,您应该这样做:

for file in ABCD[0-9][0-9][0-9][0-9][0-9][0-9].7z; do
    # stuff with "$file"
done

建议在这些情况下启用failglob(使用shopt -s failglob),这样当没有文件与模式匹配时,命令/循环就不会执行。

在这些示例中,[0-9]并不严格等同于[[:digit:]],因此如果您需要与被认为是数字的任何内容进行严格匹配,则应改用它。

要明确的是,在执行ls ABCD [0-9] [0-9] [0-9] [0-9] [0-9] [0-9] .7z时,shell会在将其传递给ls之前将全局通配符扩展为参数列表,因此ls实际上并没有做太多事情,只是回显那些参数。这与传递给grep的单引号参数形成对比,后者由grep解释为正则表达式。通配符表达式和正则表达式是两种不同的东西,因此不能指望它们的语法相同。


1
谢谢,非常全面的回答。我确实尝试过用 'ls' 转义花括号,但不幸的是它没有起作用,所以我没有尝试用 'grep'。那么在 'ls' 中没有使用花括号的方法了吗? - thisismydesign

3
你不需要使用 grep 命令,bash 就可以完成此操作:
foo=ABCD150915.7z
if [[ $foo =~ ABCD[[:digit:]]{6}.7z ]]; then
   echo "Successful match"
else
   echo "Match failed"
fi

1

由于基本的grep使用BRE(基本正则表达式),因此您需要转义花括号,其中\{\}作为重复量化器,未转义的{}将匹配字面上的{}大括号。

grep 'ABCD[[:digit:]]\{6\}\.7z'

最好使用锚点。
grep '^ABCD[[:digit:]]\{6\}\.7z$'

0

@Avinash Raj 给你的答案是正确的。但还有另一种方法。 如果你不想转义大括号(即你的 grep 表达式很长,你可能会迷失在其中),你可以使用 egrep

echo "ABCD150915.7z" | egrep "ABCD[[:digit:]]{6}.7z"

4
egrepgrep -E相同,只是前者已被弃用。详见:http://pubs.opengroup.org/onlinepubs/007908799/xcu/egrep.html。 - Tom Fenech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接