Bash in-process regular expressions

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(.*)' ]]
        echo $BASH_REMATCH is what I wanted   
        echo but just ${BASH_REMATCH[1]}

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.

(OLDER) <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

-> -> Bash in-process regular expressions


More Articles by

Find me on Google+

© Tony Lawrence

Mon Aug 4 05:18:06 2008: 4465   Taco

When trying this, I could only get it to work without the single quotes:

if [[ $input =~ foo(.*) ]]
echo $BASH_REMATCH is what I wanted
echo but just ${BASH_REMATCH[1]}

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 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
$ 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(.*)' ]]
echo $BASH_REMATCH is what I wanted
echo but just ${BASH_REMATCH[1]}

Some !~ operator doesn't work.

Sat Feb 21 10:36:53 2015: 12613   7d42)


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).

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!

Kerio Samepage

Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

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

privacy policy