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

12,578

Solution 1

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.

Solution 2

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

Solution 3

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$'
Share:
12,578
thisismydesign
Author by

thisismydesign

Updated on August 02, 2022

Comments

  • thisismydesign
    thisismydesign almost 2 years

    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.

  • Tom Fenech
    Tom Fenech over 8 years
    egrep is the same as grep -E, except that the former is deprecated.
  • thisismydesign
    thisismydesign over 8 years
    Thank you, quite comprehensive answer. I did try escaping the curly braces with 'ls' but as it didn't work unfortunately I didn't bother trying it with 'grep'. So there's no way of using curly braces this with 'ls'?