As you may already know, a lot of the features modern RegEx engines support (back referencing, lookaround assertions, etc.) are not supported by Bash RegEx engine. Following is a simple Bash script I have just created to try to explain what my end goal is:


# Make sure exactly two arguments are passed.
if [ $# -lt 2 ]
    echo "Usage: match [string] [pattern]"


if [[ ${variable} =~ ${pattern} ]]
    echo "true"
    echo "false"

So for instance, something like the following command will return false:

. match.sh "catfish" "(?=catfish)fish"

whereas the exact same expression will find a match when used in a Perl or a JavaScript regex tester.

Backreferences (e.g. (expr1)(expr2)[ ]\1\2) won't match as well.

I have simply come to the conclusion that my problem will only be solved when forcing bash to use a Perl-compatible RegEx engine. Is this doable? If so, how would I go about performing the procedure?

  • 5
    Why don't you just use perl instead of bash for scripting? And why is this question tagged javascript?
    – Marco
    Jul 26, 2013 at 1:06
  • Because using Bash is a must in my situation. And I have accidentally tagged JavaScript. I removed it :) Jul 26, 2013 at 1:11
  • 2
    Why don't you use grep with -P or using sed?
    – cuonglm
    Jul 26, 2013 at 1:32
  • 2
    But you never explain the situation/problem that made you come to the conclusion that you must have the shell do something it simply can't do. There make be a better way.
    – llua
    Jul 26, 2013 at 2:25
  • I find that backreferences do work in bash 4.3.x (Ubuntu 14.04), but not in bash 3.2x (OS X). Here is my test command: re="([a-z])[0-9]\1"; [[ a1a =~ $re ]] && echo ${BASH_REMATCH[0]} Dec 30, 2015 at 17:02

2 Answers 2


Bash doesn't support a method for you to do this at this time. You're left with the following options:

  1. Use Perl
  2. Use grep [-P|--perl-regexp]
  3. Use Bash functionality to code it

I think I would go with #2 and try and use grep to get what I want functionally. For back referencing you can do the following with grep:

$ echo 'BEGIN `helloworld` END' | grep -oP '(?<=BEGIN `).*(?=` END)'

-o, --only-matching       show only the part of a line matching PATTERN
-P, --perl-regexp         PATTERN is a Perl regular expression

    is a positive look-ahead assertion
    is a negative look-ahead assertion
    is a positive look-behind assertion
    is a negative look-behind assertion 


  • I honestly didn't know grep had a [-P|--perl-regexp] token. Thanks a lot :-) Jul 29, 2013 at 1:12
  • @FadiHannaAL-Kass - you're welcome. Thanks for the question.
    – slm
    Jul 29, 2013 at 1:14
  • 4
    For posterity, only GNU grep includes the -P option, and it's not universal. FreeBSD's grep is based on GNU, but the documentation states "This option is not supported in FreeBSD". In OSX, grep is also based on GNU, but the -P option isn't even mentioned in the man page. And on other unix systems whose grep is not GNU, you're unlikely to see -P anywhere at all. If there's the remote possibility you that portability may be useful to you in the future, I recommend avoiding OS-specific options like this.
    – ghoti
    Oct 26, 2015 at 14:22
  • pcregrep is also an option, if available.
    – Wildcard
    Apr 7, 2016 at 6:59
  • 2
    It should be noted that zsh does exactly what the OP requested, as long as the REMATCH_PCRE option is set. Jun 29, 2016 at 23:02

One could use pcregrep. It comes with the package pcre in CentOS and pcregrep in Ubuntu.

grep -P could have this issue depending on the OS / version:

-P, --perl-regexp
              Interpret PATTERN as a Perl regular expression.  This is highly experimental and grep -P may warn of unimplemented features.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.