Bash regex: how to match n times using 'grep' or 'ls'
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$'
thisismydesign
Updated on August 02, 2022Comments
-
thisismydesign almost 2 years
I'd like to match n digits the following way with
grep
orls
: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}
usinggrep
orls
. -
Tom Fenech over 8 years
-
thisismydesign over 8 yearsThank 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'?