bash 正则表达式匹配在 [[ ]] 中失败

Suu*_*hgi 5 bash regular-expression

我想通过以下方式检查用户是否在某个组中

[[ "$(getent group groupname)" =~ \busername\b ]]
Run Code Online (Sandbox Code Playgroud)

但这不起作用(bash 5.0.3)虽然以下有效:

getent group groupname | grep -E "\busername\b"
Run Code Online (Sandbox Code Playgroud)

我注意到反斜杠似乎在某个地方被吞了

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

但这也可能是-x.

任何人都可以解决这个问题吗?:-)

Sté*_*las 10

bash,\是一个像'and一样的引用运算符"。所以:

[[ "$(getent group groupname)" =~ \busername\b ]]
Run Code Online (Sandbox Code Playgroud)

是相同的:

[[ "$(getent group groupname)" =~ 'b'username'b' ]]
Run Code Online (Sandbox Code Playgroud)

bash3.2 开始,bash 确保当你在正则表达式中引用一个字符时,它会删除它作为正则表达式运算符的特殊含义(如果它有一个)(不是这种情况b)。

bash3.1 中,您将能够执行以下操作:

[[ "$(getent group groupname)" =~ '\busername\b' ]]
Run Code Online (Sandbox Code Playgroud)

如果您打开该bash31选项或设置$BASH_COMPAT为,您仍然可以这样做3.1。这也适用于zsh.

这将适用于系统扩展正则表达式库支持\b非标准扩展的系统(如最近的 GNU 系统)。

在 bash 3.2 及更高版本中,这不起作用,因为通过引用\,bash 删除了\作为正则表达式运算符的特殊性(实际上它使用\\busername\\b.

你可以做的是写它:

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

然后它将适用于 bash 3.1 和 bash 3.2+(以及 zsh 和 ksh93)。请参阅如何将正则表达式存储在 shell 变量中避免引用 shell 特有的字符时出现问题?有关更多详细信息。

不过,在这里,我会使用标准sh语法并执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)

如果用户名包含正则表达式运算符(.在用户名中很常见)或者用户名恰好与组名相同,这也更可靠。