This is my first time bash scripting so I'm probably making an easy mistake.

Basically, I'm trying to write a script that gets the groups of a user, and if they are in a certain group, it will log that accordingly. Evidently there will be more functionality, but there's no point building that when I can't even get the regex working!

So far, I have this:


regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"

# example output
groups="username : username usergroup"

echo "$groups" >> /home/jrdn/log

if [[ "$groups" =~ $regex ]]; then
    echo "Match!" >> /home/jrdn/log
    echo "No match" >> /home/jrdn/log

Every place I've tried that regex, it works. But in the bash script, it only ever outputs the $groups, followed by No match. So can someone tell me what's wrong with it?

  • 1
    What makes you think anything is wrong with it?
    – manatwork
    Oct 3 '13 at 14:17
  • 1
    @jrdnhannah then try to slowly re-create your target regexp, first match ^([a-zA-Z0-9\-_]+) then add the colon and so on... you should find out pretty soon, where is the problem.
    – peterph
    Oct 3 '13 at 14:35
  • 2
    Same here with bash 4.2.45. Escaping the underscore fixed it. Weird. @jrdnhannah could you write that up as an answer and accept it please?
    – terdon
    Oct 3 '13 at 14:54
  • 1
    Since I've only just signed up to the Unix SE, it requires me to wait 8 hours before answering my own. Happy to mark it as answered if somebody else does, though.
    – jrdn
    Oct 3 '13 at 15:07
  • 4
    @terdon bash just calls libc's regex functions, probably. So it depends on the libc version, not the bash version. See my answer... (Or maybe even on the collation sequence you have in use)
    – derobert
    Oct 3 '13 at 15:30

From man 7 regex:

A bracket expression is a list of characters enclosed in "[]". …

… To include a literal '-', make it the first or last character…. [A]ll other special characters, including '\', lose their special significance within a bracket expression.

Trying the regexp with egrep gives an error:

$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end

Here is a simpler version, that also gives an error:

$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end

Since \ is not special, that is a range, just like [a-z] would be. You need to put your - at the end, like [_-] or:

echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup

This should work regardless of your libc version (in either egrep or bash).

edit: This actually depends on your locale settings too. The manpage does warn about this:

Ranges are very collating-sequence-dependent, and portable programs should avoid relying on them.

For example:

$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'

Of course, even though it didn't error, it isn't doing what you want:

$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'

It's a range, which in ASCII, includes \, [, ^, and _.

  • Interesting. My egrep gives no error, just matches it correctly.
    – manatwork
    Oct 3 '13 at 15:35
  • @manatwork your collation sequence probably allows the range....
    – derobert
    Oct 3 '13 at 15:36
  • I not know much about collation. You mean this: LC_COLLATE="en_US.UTF-8"?
    – manatwork
    Oct 3 '13 at 15:40
  • @manatwork I've edited the question to give an example. Note it may be different on your system, because sometimes those collation (sorting) sequences change.
    – derobert
    Oct 3 '13 at 15:41
  • 1
    @manatwork Its OK, I almost filed a bug report before I noticed the attempt to escape -...
    – derobert
    Oct 3 '13 at 15:44

General rule with regexps (and any bugs in larger pieces of code): cut it down and rebuild it step by step or use bisecting - whatever works better for you.

In this case the culprit turned out to be the underscore - escaping it with a backslash has made it work.

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.