Bash acquired in-process regular expressions in version 3.0, but I never noticed, probably because most of the machines I'm using are Bash 2.05b. As I'm not necessarily in a position to upgrade any old box I happen to be working on, I tend to stick to the stuff that will work anywhere, which often means piping out to grep for a regular expression test.
However, should you have an environment where you can depend on this feature being present, in-process regexes obviously avoid firing up another process for grep and are much more neat to write or read.
The syntax is Perlish, using "=~". You also have access to sub-matches: $BASH_REMATCH is the string matched, ${BASH_REMATCH[1]} is the first parenthesided match, and so on. So, we can do:
if [[ "$input" =~ 'foo(.*)' ]] then echo $BASH_REMATCH is what I wanted echo but just ${BASH_REMATCH[1]} fi
and other more interesting tasks.
Note discussion of quotes in the comments!
Set 'nocaseglob' for case insensitivity. The return value for these is 0 for a match, 1 for no match, and (how thoughtful) 2 if the expression is syntactically incorrect, so watch out for the other side of that "if" - a non-zero return might mean you screwed up your pattern.
Got something to add? Send me email.
More Articles by Tony Lawrence © 2015-02-21 Tony Lawrence
Write a paper promising salvation, make it a 'structured' something or a 'virtual' something, or 'abstract', 'distributed' or 'higher-order' or 'applicative' and you can almost be certain of having started a new cult. (Edsger W. Dijkstra)
Mon Aug 4 05:18:06 2008: 4465 Taco
When trying this, I could only get it to work without the single quotes:
Sat Jul 18 15:57:55 2009: 6644 anonymous
me too, single or double quotes don't work... strange syntax...
Mon Mar 29 10:54:01 2010: 8294 vayerx
Any part of the pattern may be quoted to force it to be matched as a string.
Sun Aug 8 02:25:43 2010: 8878 VertigoRay
Worked for me as it was shown in the article ...
$ uname -srvo
Linux 2.6.32.8-grsec-2.1.14-modsign-xeon-64 #2 SMP Sat Mar 13 00:42:43 PST 2010 GNU/Linux
Thanks for the post. Really helped me out.
Mon Sep 27 13:17:09 2010: 9012 JonathanCross
I must use unquoted regex as well.
$ if [[ sam =~ ^bob|sam$ ]];then echo match;else echo NO match;fi
match
$ if [[ sam2 =~ ^bob|sam$ ]];then echo match;else echo NO match;fi
NO match
$ bash --version
GNU bash, version 3.2.39(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
Mon Jun 9 14:57:12 2014: 12480 Rei
Thx !
And for invert match:
if ! [[ "$input" =~ 'foo(.*)' ]]
then
echo $BASH_REMATCH is what I wanted
echo but just ${BASH_REMATCH[1]}
fi
Some !~ operator doesn't work.
Sat Feb 21 10:36:53 2015: 12613 7d42)
@TonyLawrence
As others have noted, the regex pattern should not be quoted. If quotes are literally part of the match, then they should be escaped with a backslash. Quotes can be used to match a string, but in that case why bother using regex?
Ideally the example would begin as follows:
[[ $input =~ foo(.*) ]]
Note that the left side does not need to be quoted here (word splitting and pathname expansion are not performed for [[ expressions).
@JonathanCross
You used the example [[ sam =~ ^bob|sam$ ]]. This will match strings starting with bob (i.e. bobby) and/or ending with sam (i.e. rossam). You probably want this: [[ sam =~ ^(bob|sam)$ ]]
Sat Feb 21 11:41:01 2015: 12614 TonyLawrence
Well, as you can see from the comments, other people found quotes worked. I can assure you that they did when I wrote this, but today on the same machines, it does not - of course Bash has been upgraded more than once since then - it's been almost ten years!
------------------------
Printer Friendly Version
Bash in-process regular expressions Copyright © September 2005 Tony Lawrence
Have you tried Searching this site?
This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.
Contact us
Printer Friendly Version