Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This is about Bash development and coding of portable Bash scripts that use RegEx.

Using Bash RegEx, on a Mac, I can do this:

coconut-mac$ a='bananacoconutman'; [[ "$a" =~ banana(.*?)man ]] && echo FOUND ${BASH_REMATCH[1]}
FOUND coconut

Nice. Useful in many places. Like.

When I try doing this, it fails:

coconut-mac$ a='<title>coconut</title>'; [[ "$a" =~ \<title\>(.*?)\</title\> ]] && echo FOUND ${BASH_REMATCH[1]}

The exact same command runs perfectly on the penguin:

coconut-linux$ a='<title>coconut</title>'; [[ "$a" =~ \<title\>(.*?)\</title\> ]] && echo FOUND ${BASH_REMATCH[1]}
FOUND coconut
  • Why?
  • How to fix it to make the script portable?

EDIT: On the Mac:

OS X version: 10.8.2
Bash version: 4.2.37(2)-release

on Ubuntu 12.04 LTS:

Linux kernel version: 3.2.0-29-generic-pae
Linux version: Ubuntu 12.04.1 LTS
Bash version: 4.2.24(1)-release
share|improve this question

migrated from Oct 3 '12 at 13:59

This question came from our site for professional and enthusiast programmers.

What versions of grep are you using on each system? There is no single version of Linux - what flavor/version are you using? – Matt Ball Oct 3 '12 at 2:22
s/grep/bash/ >.> – Ignacio Vazquez-Abrams Oct 3 '12 at 2:26
up vote 3 down vote accepted

On my Mac, info bash / =~ RET says:

An additional binary operator, =~', is available, with the same precedence as==' and `!='. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex3)).

man 3 regex says:

A repetition operator (?',*', +', or bounds) cannot follow another repetition operator. A repetition operator cannot begin an expression or subexpression or follow^' or `|'.

I don't see any analogous documentation in GNU regex's man 3 regex or info regex.

If I remove the ? from your (.*?) and do the following, it works on both OSes:

$ a='<title>coconut</title>'; [[ "$a" =~ \<title\>(.*)\</title\> ]] && echo FOUND ${BASH_REMATCH[1]}
FOUND coconut
share|improve this answer
Nice write-up!! – Robottinosino Oct 3 '12 at 2:45

This would probably be the answer:

Default bash on Darwin (10.8.1/2):

GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)

Default bash on, say, Ubuntu 12 LTS:

GNU bash, version 4.2.24(1)-release (x86_64-pc-linux-gnu)

Making it portable would be stepping away from newer bash quirks and using things like sed, awk, whatnot.

share|improve this answer
Thanks! That's it... – Robottinosino Oct 3 '12 at 3:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .