【问题标题】:BASH =~ contains substring: "+" or a regex character behaviorBASH =~ 包含子字符串:“+”或正则表达式字符行为
【发布时间】:2016-11-22 18:11:01
【问题描述】:

想知道为什么以下内容对角色不起作用:+

字符 "\""(""*" 有意义,即 * 将扩展为当前目录中的文件夹/文件(在命令行 shell 扩展期间),类似地 \( 将期望关闭字符起作用,但我的理解是 "+" 应该像 "-" 那样工作。

PS:我知道在 IF 语句中加上双引号,即“${o}”,将适用于下面我的测试用例中的所有字符。在带或不带双引号的 IF 语句中使用 \${o} 将使所有检查失败。

$ for o in - + \` ~ \~ , _ = / \\ ! @ \# $ \$ % ^ \& \* \( \); do a="a${o}b${o}c";if [[ $a =~ ${o} ]]; then echo "${o} exists in $a and =~ works"; else echo -e "\ncharacter ${o} doesn't work with =~\n"; fi; done
- exists in a-b-c and =~ works

character + doesn't work with =~

` exists in a`b`c and =~ works
/home/ubuntu exists in a/home/ubuntub/home/ubuntuc and =~ works
~ exists in a~b~c and =~ works
, exists in a,b,c and =~ works
_ exists in a_b_c and =~ works
= exists in a=b=c and =~ works
/ exists in a/b/c and =~ works

character \ doesn't work with =~

! exists in a!b!c and =~ works
@ exists in a@b@c and =~ works
# exists in a#b#c and =~ works
$ exists in a$b$c and =~ works
$ exists in a$b$c and =~ works
% exists in a%b%c and =~ works
^ exists in a^b^c and =~ works
& exists in a&b&c and =~ works

character * doesn't work with =~


character ( doesn't work with =~

) exists in a)b)c and =~ works

【问题讨论】:

  • 不,* 没有扩展到文件列表——在正则表达式中,它的意思是“前面的标记的零个或多个”。
  • @CharlesDuffy 正确,我的意思是“for”语句。
  • ...但是你正在逃避它,就像\*,对于for 语句,所以它没有在那里做任何这样的替换。
  • 顺便说一句,^ 并不像你想象的那样工作。 [[ hello =~ ^ ]] 是真的,即使 hello 里面没有 ^,因为 ^ 是“行首”的正则表达式。同样,$ 表示行尾。
  • 同意。我逃脱了它。很高兴知道 =~ + ?和 * 像正则表达式模式一样工作。我正在失去我的技能:)。如果不使用 " 双引号,如果我可以使 + 或 ? 字符起作用,即 ${o}${o} 在 IF 语句中作为 ++ 或 ?? ,这将是有趣的,其中第一个字符 + 将是litteral 和 second 将用作正则表达式 + 或 ? 或 *。

标签: linux bash shell command-line escaping


【解决方案1】:

这个问题背后的根本误解是=~ 是一个子字符串搜索运算符。 不是

=~ 的右侧被评估为 POSIX ERE 表达式。 =~ 因此是一个正则表达式匹配运算符,当右侧被引用以使其内容为文字时(或者当已知此字符串在解释为 ERE 时仅匹配自身时),它恰好经常用于搜索。


+,在正则表达式中,表示“前一个令牌的 1 个或多个”——就像 * 表示“前一个令牌的 0 个或多个”一样。

因此,[[ $foo =~ + ]][[ $foo =~ * ]] 都没有意义,因为它们正在检查零个或多个前面的标记根本不存在

同样,() 在 ERE 中作为匹配组的开始和结束都具有意义,因此当它们被裸露(未转义/未引用)时,它们会导致无效的正则表达式。

相比之下,如果引用扩展,则包含的所有字符都将被视为文字,而不是被视为正则表达式元字符,从而导致可能的预期行为。


如果要检查字符串中是否包含文字字符,请引用它 -- [[ $foo =~ "$o" ]] -- 或使用全局样式模式:[[ $foo = *"$o"* ]]

【讨论】:

    猜你喜欢
    • 2011-07-22
    • 1970-01-01
    • 2014-03-23
    • 2011-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多