7

I would like to check whether a user is in a certain group via

[[ "$(getent group groupname)" =~ \busername\b ]]

but this does not work (bash 5.0.3) although the following works:

getent group groupname | grep -E "\busername\b"

I noticed that the backslashes appear to be swallowed at some place

bash -cx '[[ "$(getent group groupname)" =~ \busername\b ]]'
++ getent group groupname
+ [[ groupname:x:24:username =~ busernameb ]]

but this could also be an effect of -x.

Can anyone clear this up? :-)

1 Answer 1

12

In bash, \ is a quoting operator like ' and ". So:

[[ "$(getent group groupname)" =~ \busername\b ]]

is the same as:

[[ "$(getent group groupname)" =~ 'b'username'b' ]]

Since bash 3.2, bash makes sure than when you quote a character in a regexp, it removes its special meaning as a regexp operator if it had one (which is not the case of b).

In bash 3.1, you would have been able to do:

[[ "$(getent group groupname)" =~ '\busername\b' ]]

And you can still do if you turn on the bash31 option or set $BASH_COMPAT to 3.1. That would also work in zsh.

That would have worked on systems where the system extended regular expression library supports that \b non-standard extension (like on recent GNU systems).

In bash 3.2 and above, that doesn't work because by quoting the \, bash removes the specialness of \ as a regex operator (in effect it calls the regex library with \\busername\\b.

What you can do though is write it:

regexp='\<username\>' # here using the slightly more portable \< \> instead of \b
[[ "$(getent group groupname)" =~ $regexp ]] # make sure $regexp is *not* quoted

Then it would work with both bash 3.1 and bash 3.2+ (and zsh and ksh93). See How does storing the regular expression in a shell variable avoid problems with quoting characters that are special to the shell? for more details on that.

Here though, I'd use standard sh syntax and do:

group=groupname
user=username

group_definition=$(getent -- group "$group") || exit
case ,${group_definition##*:}, in
  (*,"$user",*) printf '%s\n' "$user is in the $group group\n"
esac

Which also works more reliably if the user name contains regexp operators (. is common in user names) or the user name happens to be the same as the group name.

3

You must log in to answer this question.

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