Bash逃避脚本& sed捕获组

时间:2014-09-01 15:52:31

标签: regex bash sed escaping capture

我在bash脚本中有一个我不理解的奇怪行为。

基本上在下面的代码中我尝试转义元字符......

while IFS=, read _type _content; do

  if [ -z "$patternfilter" ]; then
    if [ "$_type" == "rex" ]; then
      patternfilter="$_content"
    elif [ "$_type" == "txt" ]; then
      patternfilter="`echo "$_content" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
    fi
  else
    if [ "$_type" == "rex" ]; then
      patternfilter="$patternfilter|$_content"
    elif [ "$_type" == "txt" ]; then
      patternfilter="$patternfilter|`echo "$_content" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
    fi
  fi
done < $patternfile

输出口给我以下内容:

  

blabal \ 1bla \ 1blabla \ 1toto \ 1COM

而不是:

  

blabal \(BLA \)布拉布拉\ [TOTO \] \。com

如果我直接在控制台中输入它运作的代码......我会想念一些东西,但我不知道是什么。

[root]# patternfilter="blabal(bla)blabla[toto].com"
[root]# echo "$patternfilter" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'
blabal\(bla\)blabla\[toto\]\.com

2 个答案:

答案 0 :(得分:4)

您无法可靠地转义sed中的字符,因为字符是否需要转义是上下文相关的。此外,shell是一个可以从中调用工具的环境。用于操作文本的标准UNIX工具是awk。只需让你的shell调用awk来做所有事情。顺便说一下,使用`...`而不是$(...)将解释双重转义,而使用不带-r的读取将扩展转义。

SInce awk可以操作字符串以及RE几乎肯定不会逃避任何东西,因为逃避字符的通常理由是尝试使你的工具只能在RE上工作在字符串上,这是不可能的任务。

如果您告诉我们您正在尝试使用patternfilter以及一些示例输入和预期输出,我们可以向您展示如何简单而强大地执行此操作。

答案 1 :(得分:2)

检查下一个脚本:

while IFS=, read -r line; do
    result1="`echo "$line" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g'`"
    echo "1=$result1="

    result2="$(echo "$line" | sed -re 's/([-^[{}()*+/.,;?$|#\\])/\\\1/g' -e 's/]/\\]/g')"
    echo "2=$result2="
done <<'EOF'
blabal(bla)blabla[toto].com
EOF

打印:

1=blabal\1bla\1blabla\1toto]\1com=
2=blabal\(bla\)blabla\[toto\]\.com=

反引号的instad使用$(),与result2=...行一样。 (并始终使用-r作为read -r

使用printf "%q"这样的

,您可以更简单地逃避
while IFS=, read _type _content; do
res=$(printf "%q" "$_content")
echo "==$res=="
done <<EOF
txt,blabal(bla)blabla[toto].com
EOF

打印什么

==blabal\(bla\)blabla\[toto\].com==

但是,请阅读@ EdMorton的回答。