bash 脚本中的正则表达式

bash 脚本中的正则表达式

这是我第一次编写 bash 脚本,所以我可能犯了一个简单的错误。

基本上,我正在尝试编写一个脚本来获取用户的组,如果他们位于某个组中,它将相应地记录下来。显然会有更多的功能,但是当我什至无法让正则表达式工作时,构建这些功能就没有意义了!

到目前为止,我有这个:

#!/bin/bash

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
else
    echo "No match" >> /home/jrdn/log
fi

我尝试过该正则表达式的每个地方,它都有效。但在 bash 脚本中,它只输出$groups, 后跟No match.那么有人可以告诉我这是怎么回事吗?

答案1

man 7 regex

括号表达式是用“[]”括起来的字符列表。 ……

...要包含文字“-”,请将其作为第一个或最后一个字符...。 [A]所有其他特殊字符,包括“\”,在括号表达式中都会失去其特殊意义。

尝试使用egrep 进行正则表达式会出现错误:

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

这是一个更简单的版本,也给出了一个错误:

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

由于\并不特殊,所以这是一个范围,就像[a-z]本来的那样。你需要把你的放在-最后,比如[_-]或者:

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

无论您的 libc 版本如何(在egrep或bash中),这都应该有效。

编辑:这实际上也取决于您的区域设置。联机帮助页确实警告了这一点:

范围非常依赖于整理顺序,可移植程序应避免依赖它们。

例如:

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

当然,即使它没有出错,它也没有做你想要的事情:

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

它是一个范围,在 ASCII 中包括\[^_

答案2

正则表达式的一般规则(以及较大代码段中的任何错误):逐步削减并重建它或使用二等分 - 无论哪种方式对您更有效。

在这种情况下,罪魁祸首竟然是下划线——用反斜杠转义它就可以了。

相关内容