Bash 用sed替换带有缩进的文本块

Bash 用sed替换带有缩进的文本块,bash,sed,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和bbb之间的所有内容替换为ccc。此外,它还使用它找到的相同缩进: fff aaa ddd ddd bbb fff 将被处理为 fff aaa ccc bbb fff 但

我有下一个代码:

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和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: /* R+ Testy */ (with escaped / & *)  
STOPSEQREG: /* R- */ (with escaped / & *)   
ENUARRAY[i]: case AAA:\n    break;  
START,STOPSEQREG&ENUMARRAY[i]包含/,*,空格,:,;,+及-。数组的元素还包含\n。/&*符号用\转义

运行时显示的错误是“错误的反向引用”

谁能帮帮我吗

提前谢谢

p.S.变量示例:

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: /* R+ Testy */ (with escaped / & *)  
STOPSEQREG: /* R- */ (with escaped / & *)   
ENUARRAY[i]: case AAA:\n    break;  

我发现了几件事:

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

概述:对于这种复杂的东西,我个人总是希望使用一种具有良好正则表达式和shell支持的语言,例如Python/Perl/Ruby/Groovy等。这避免了BASH(或其他shell)/SED引用地狱怪癖和问题,允许进行单元/集成测试/调试和日志记录,但有时显然会带来自己的负担,或者,不幸的是,这并不总是可能的。

您能提供使用带有可变赋值的
sed
的脚本吗?完整脚本:以下是测试文件:源:和目标:1)我应该使用什么来代替-ire?2) 我尝试过反斜杠$符号或使用Cometing,比如
;"'$'"!b
但它仍然不起作用。哦,是的,应该加上这个。。。看我更新的答案!(简而言之,
-i-re
)下面是代码现在的样子:
sed-i-re:x;N;\$!bx;s@(^|N)(\s*)(${START})\N(.+)\N\2(${STOPSEQREG})(\N|\$)\1\2\3\N\2${ENUMARRAY[$i]}\N\2\5\6@g“$f
但该代码不能替代任何东西。完整脚本:第一步是停止错误,这是一个好的开始。正确使用正则表达式完全是另一个问题;我要做的(除了使用另一种语言——见上文)是预先将正则表达式构建为字符串,并将其回显到控制台。这样,您就可以使用一些有用的工具,如www.regexr.com来调试regex,并使用您的输入进行测试。顺便说一句,我不确定它的目的是什么,但我怀疑你希望
\2
\n
之后,在
之前(${STOPSEQREG})
(在LHS上)。另外,我假设您仅在这里使用UNIX行结尾(
\n
),否则您需要重新考虑一些内容。