我真的很难理解这种行为:
stackExchange@test:~$ if [[ "two words" =~ \bwords ]]; then echo hi; fi; #(I'd expect this one worked)
stackExchange@test:~$ if [[ "two words" =~ \\bwords ]]; then echo hi; fi; #(or at least this one...)
stackExchange@test:~$ if [[ "two words" =~ \\\bwords ]]; then echo hi; fi;
stackExchange@test:~$ if [[ "two words" =~ \\\\bwords ]]; then echo hi; fi;
stackExchange@test:~$ put_in_a_variable=\\bwords
stackExchange@test:~$ if [[ "two words" =~ $put_in_a_variable ]]; then echo hi; fi;
hi
stackExchange@test:~$
我知道我的变量包含\bword
并且在条件表达式的模式部分中得到了扩展,但我真的无法理解为什么使用内联 shell 转义似乎不可能实现相同的行为。
我不想做类似的事情if [[ "two words" =~ $(echo \\bwords) ]]; then echo hi; fi;
;太奇怪了……
谢谢,
弗朗西斯科
答案1
正则表达式部分中反斜杠的作用[[ str =~ rex ]]
是引用以下字符(就像将其放在单引号中一样),并且在 bash 中以及自版本 3.2 以来,指示它对其进行文字匹配 (1)。因为b
不是特殊的,\b
将变成只是b
, 但是'\'
, "\\"
or\\
将变成\\
为了匹配文字反斜杠:
[[ abwords =~ \bwords ]] && echo "<$BASH_REMATCH>"
<bwords>
[[ 'a\bwords' =~ \\bwords ]] && echo "<$BASH_REMATCH>"
<\bwords>
# conversely, '|' is just like \|
[[ 'a|words' =~ a'|'words ]] && echo "<$BASH_REMATCH>"
<a|words>
将正则表达式放入变量中的想法很好。另一种方法是使用包装函数:
rematch() [[ $1 =~ $2 ]]
if rematch 'two words' '\bwords\b'; then
echo "<$BASH_REMATCH>"
fi
<words>
无论如何,应用这些解决方法后,由于\b
是非标准扩展正则表达式运算符(来自 perl),因此它是否有效将取决于系统的正则表达式库是否支持它。根据系统的不同,您可能会更幸运地使用这些单词边界运算符的一些替代语法,例如\<
/\>
或[[:<:]]
/ [[:>:]]
。
(1):如其记录手动的:
模式的任何部分都可以被引用以强制引用部分作为字符串进行匹配
请注意,在 shell 中,字符是引实际上是特别标记,因此解析器的任何后续处理都可以根据字符串的一部分是否被引用或不被引用来决定。