简体   繁体   中英

Bash regex: how to match n times using 'grep' or 'ls'

I'd like to match n digits the following way with grep or ls :

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

The above is not working and I've tried quite many ways now... How can this be done?

I understand there are other ways, but please note that I want to know if this specifically is possible: [[:digit:]] and {6} using grep or ls .

Yes it's possible, using one of two methods:

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

Enabling Extended regular expression mode with -E means that the curly braces are understood.

Alternatively, you can escape the curly braces:

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

If you want to list all files matching the pattern, you can use a glob expansion instead:

ls ABCD[0-9][0-9][0-9][0-9][0-9][0-9].7z

...and if you're thinking about looping through those files, you should do it like this:

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

It's advised to enable failglob in either of these cases (use shopt -s failglob ), so that when no files match the pattern, the command / loop isn't executed.

The [0-9] in these examples isn't strictly the same as [[:digit:]] , so if you require a strict match with anything considered a digit, then you should use that instead.

To be clear, when you do ls ABCD[0-9][0-9][0-9][0-9][0-9][0-9].7z , the shell expands the glob into a list of arguments before passing it to ls , so ls isn't really doing much other than echoing those arguments. This contrasts with the single quoted argument passed to grep , which is interpreted by grep as a regular expression. Glob expressions and regular expressions are two different things, so you can't expect the syntax for them to be the same.

You need to escape curly braces since basic grep uses BRE (Basic Regular Expression) in which \\{\\} acts like a repeatation quantifier where unescaped {} would match literal { , } braces.

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

Better to use anchors.

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

You don't need grep for this with bash :

foo=ABCD150915.7z
if [[ $foo =~ ABCD[[:digit:]]{6}.7z ]]; then
   echo "Successful match"
else
   echo "Match failed"
fi

The answer @Avinash Raj gave you is correct. But there is another way too. If you don't want to escape the braces(ie your grep expression is much longer and you can get lost in them) you can use egrep :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM