Bash if 语句中的正则表达式匹配

标签 regex bash if-statement

我做错了什么?

尝试匹配任何包含空格、小写字母、大写字母或数字的字符串。特殊字符也不错,但我认为这需要转义某些字符。

TEST="THIS is a TEST title with some numbers 12345 and special char *&^%$#"

if [[ "$TEST" =~ [^a-zA-Z0-9\ ] ]]; then BLAH; fi

这显然只测试大写、小写、数字和空格。虽然不起作用。

* 更新 *

我想我应该更具体一些。这是实际的代码行。

if [[ "$TITLE" =~ [^a-zA-Z0-9\ ] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; fi

* 更新 *

./anm.sh: line 265: syntax error in conditional expression
./anm.sh: line 265: syntax error near `&*#]'
./anm.sh: line 265: `  if [[ ! "$TITLE" =~ [a-zA-Z0-9 $%^\&*#] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; return; fi'

最佳答案

关于 bash 的 [[ ]] 构造,有几件重要的事情需要了解。第一个:

Word splitting and pathname expansion are not performed on the words between the [[ and ]]; tilde expansion, parameter and variable expansion, arithmetic expansion, command substitution, process substitution, and quote removal are performed.

第二件事:

An additional binary operator, ‘=~’, is available,... the string to the right of the operator is considered an extended regular expression and matched accordingly... Any part of the pattern may be quoted to force it to be matched as a string.

因此,=~ 两侧的 $v 将扩展为该变量的值,但结果不会是分词或路径名-展开。换句话说,在左侧不加引号保留变量扩展是完全安全的,但您需要知道变量扩展将发生在右侧。

所以如果你写:[[ $x =~ [$0-9a-zA-Z] ]],右边正则表达式中的 $0 将是在解释正则表达式之前展开,这可能会导致正则表达式无法编译(除非 $0 的展开以 ascii 值小于数字的数字或标点符号结尾)。 如果你像这样引用右侧[[ $x =~ "[$0-9a-zA-Z]"]],那么右侧将被处理作为普通字符串,而不是正则表达式(并且 $0 仍将被扩展)。在这种情况下,您真正​​想要的是 [[ $x =~ [\$0-9a-zA-Z] ]]

类似地,[[]] 之间的表达式在解释正则表达式之前被拆分为单词。因此正则表达式中的空格需要转义或引用。如果您想匹配字母、数字或空格,您可以使用:[[ $x =~ [0-9a-zA-Z\] ]]。其他字符同样需要转义,例如 #,如果不加引号,它会开始注释。当然,您可以将模式放入变量中:

pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...

对于包含大量需要转义或引用才能通过 bash 的词法分析器的字符的正则表达式,许多人更喜欢这种风格。但要注意:在这种情况下,您不能引用变量扩展:

# This doesn't work:
if [[ $x =~ "$pat" ]]; then ...

最后,我认为您要做的是验证变量是否仅包含有效字符。执行此检查的最简单方法是确保它不包含无效字符。换句话说,像这样的表达式:

valid='0-9a-zA-Z $%&#' # add almost whatever else you want to allow to the list
if [[ ! $x =~ [^$valid] ]]; then ...

! 否定测试,将其变成“不匹配”运算符,[^...] 正则表达式字符类表示“除...”。

参数扩展和正则表达式运算符的组合可以使 bash 正则表达式语法“几乎可读”,但仍然存在一些陷阱。 (不总是存在吗?)一个是你不能将 ] 放入 $valid,即使 $valid 被引用,除了在一开始。 (这是一个 Posix 正则表达式规则:如果你想在字符类中包含 ],它需要放在开头。- 可以放在开头或结尾,所以如果你同时需要]-,你需要以]开始,以-结束,导致正则表达式“我知道我在做什么”表情符号:[][-])

关于Bash if 语句中的正则表达式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18709962/

相关文章:

java - 即使语句有效,也不输入 if 条件

java - 如何修复 if 和 else if 语句未选择正确的语句

PHP重命名文件,以特殊名称开头?

python - 获取字符串中字符串的特定值

linux - 使用新的组 ID 更新/etc/group

linux - 如何计算 Bash 变量中的字符数

javascript - 处理多个 "else if"语句。降低圈复杂度

java - 正则表达式拆分嵌套坐标字符串

Java 单个正则表达式作为所有字母或 6 长度的严格字母数字

python - 如何将字符串格式应用于 bash 命令(通过子进程合并到 Python 脚本中)?