如何用sed递归替换字符?

Ish*_*nka 14 linux bash regex sed

是否可以在不再次迭代相同序列的情况下递归替换出现的字符序列?

通过sed在以下场景中执行 a ,我可以获得提到的输出。

$ echo XX | sed -e 's/XX/XoX/g'
XoX  
$ echo XXX | sed -e 's/XX/XoX/g'
XoXX  
$ echo XXXX | sed -e 's/XX/XoX/g'
XoXXoX  
Run Code Online (Sandbox Code Playgroud)

但是,我希望输出遵循以下行为。

输入:

XX
XXX
XXXX
Run Code Online (Sandbox Code Playgroud)

预期输出:

XoX
XoXoX
XoXoXoX
Run Code Online (Sandbox Code Playgroud)

是否可以单独使用 sed 实现预期的行为?

Goh*_*ohu 25

你可以做:

> echo XXXX | sed -e ':loop' -e 's/XX/XoX/g' -e 't loop'
XoXoXoX
Run Code Online (Sandbox Code Playgroud)

和:

  • -e ':loop' : 创建一个“循环”标签
  • -e 't loop' : 如果先前的替换成功,则跳转到“循环”标签


Kam*_*ski 10

在这种特殊情况下,前瞻或后视将很有用。我认为 GNUsed不支持这些。与perl

perl -ne 's/X(?=X)/Xo/g; print;'
Run Code Online (Sandbox Code Playgroud)

您还可以使用lookbehind和lookahead,例如:

s/(?<=X)(?=X)/o/g
Run Code Online (Sandbox Code Playgroud)

在哪里:

(?<=X)是一个正向后视,一个零长度断言确保我们在当前位置之前有一个 X
(?=X)是一个正向前瞻,一个零长度断言确保我们在当前位置之后有一个 X

在 perl 单行中使用:

perl -pe 's/(?<=X)(?=X)/o/g' inputfile
Run Code Online (Sandbox Code Playgroud)

在哪里:

-p 使 Perl 假设一个循环,并隐式打印当前行


Dig*_*uma 5

循环答案是执行您所要求的一般方法。

但是,就您的数据而言,假设您使用的是 GNU,您可以简单地执行以下操作:

sed 's/\B/o/g'
Run Code Online (Sandbox Code Playgroud)

\b\B选项的正则表达式的扩展

  • \b 匹配单词边界,即从“单词”字符到“非单词”字符的转换,反之亦然
  • \B匹配 的反义词\b。即间隙“内”字。这允许我们根据需要在单词内部而不是外部插入字符。

在线试用

这假设输入字符实际上都是“单词”字符。


或者,如果您没有 GNU sed,或者如果输入字符不全是“单词”字符,您仍然可以在不循环的情况下实现您的目标:

sed 's/./&o/g;s/o$//'
Run Code Online (Sandbox Code Playgroud)

这只是o在每个字符之后放置一个,然后o从字符串中删除最后一个。

在线试用