用sed替换带缩进的文本块

时间:2014-11-09 09:29:03

标签: bash sed

我有下一个代码:

echo -e '  aaa\nddd\nddd\n  bbb' | sed -re ':x; N; $!b x; s/(^|\n)(\s*)(aaa)\n(.*?)\n\2(bbb)(\n|$)/\1\2\3\n\2ccc\n\2\5\6/g'

该代码取代了aaa和amp;之间的所有内容。 bbb与ccc。它也使用它找到的相同缩进:

fff
   aaa
   ddd
   ddd
   bbb
fff

将被处理为

fff
   aaa
   ccc
   bbb
fff

但是有一个问题。我无法移植它来使用我的变量:

sed -ire ":x; N; $!b x; s@(^|\n)(\s*)(${START})\n(.*?)\n\2(${STOPSEQREG})(\n|$)@\1\2\3\n\2${ENUMARRAY[$i]}\n\2\5\6@g" $f

START,STOPSEQREG& ENUMARRAY [i]包含/,*,空格,:,;,+和 - 。阵列的元素也包含\ n。 /& *符号通过\进行转义。

运行时显示的错误是"反差错误"。

请有人帮助我吗?

提前致谢。

P.S。变量示例:

START: /* R+ Testy */ (with escaped / & *)  
STOPSEQREG: /* R- */ (with escaped / & *)   
ENUARRAY[i]: case AAA:\n    break;  

1 个答案:

答案 0 :(得分:1)

我发现的一些事情:

  • 您需要在sed脚本中引用$,因为BASH可能会先到达那里并将它们解释为空变量。因此,请尝试$!b(\n|$),而不是\$!b(\n|\$)
  • 有可能简化正则表达式 - 例如可以(.*?)缩减为(.+)
  • ...但最重要的是,不要将-ire与(GNU)sed 一起使用。 r被用作-i(备份)的参数,因此您的正则表达式被视为基本正则表达式,这需要转义每个括号并且不支持{{1}这就是为什么sed认为那里没有捕获的组。请改用\s。请参阅GNU SED manual和此问题:In-place sed command not working

一般而言:对于这种复杂的事情,我个人总是寻求具有正当的正则表达式和shell支持的语言,例如: Python / Perl / Ruby / Groovy等。这避免了BASH(或其他shell)/ SED引用地狱 怪癖和问题,允许单元/集成测试/调试和日志记录,但显然有时会带来自己的包袱,或者不幸的是,它总是不可能。