【问题标题】:Repeated regex replacements with overlapping lookbehinds重复的正则表达式替换与重叠的lookbehinds
【发布时间】:2021-01-26 17:11:22
【问题描述】:

我想要

oy 1 x 1 x 1
   1 x 1 x 1

成为

oy 1 y 1 y 1
   1 x 1 x 1

(基本上,如果行以oy开头,则将x替换为y,重复使用y

我试过了

echo "oy 1 x 1 x 1" | sed -E "s/(o(.)(.*))x/\1\2/g"
echo "oy 1 x 1 x 1" | perl -pe "s/(?<=o)(.)(.*)x/\1\2\1/g"
echo "oy 1 x 1 x 1" | perl -pe "s/o(.)(.*)\Kx/\1/g"

但每个只替换最后一次。

这些非贪婪的变种

echo "oy 1 x 1 x 1" | perl -pe "s/(?<=o)(.)(.*?)x/\1\2\1/g"
echo "oy 1 x 1 x 1" | perl -pe "s/o(.)(.*?)\Kx/\1/g"

只替换第一个出现的地方。

我还能尝试什么?

【问题讨论】:

  • perl 不支持可变长度后视,否则只有正则表达式的解决方案是可能的..

标签: regex perl sed


【解决方案1】:

这可能对你有用(GNU sed):

sed -E ':a;s/\<(o(.) .*)x/\1\2/;ta' file

如果有一个单词oy,其中y 是任何字符,则匹配该字符并用它替换该行其余部分的任何x

【讨论】:

  • 在我看来模式应该是^(o(.) .*)x,据说整行必须以oy开头。
  • 您愿意解释一下我的试验有什么不同吗?似乎相关部分只是:a;;ta
  • @bers 它们形成一个循环,只要替换成功,t 就会分支到标签a.. 这类似于perl -pe 'while(s/^o(.).*?\Kx/$1/){}'
  • @WiktorStribiżew 是的,这是我的一个习惯/错误,它试图通过参数化解决方案来抢占用户的下一个问题。如果您愿意,当然可以使用/\&lt;oy\&gt;/{...} 包围解决方案。
【解决方案2】:
$ perl -pe 's/x/substr($_,1,1)/ge if /^o/' ip.txt
oy 1 y 1 y 1
   1 x 1 x 1
  • /^o/ 如果行以 o 开头
  • substr($_,1,1) 输入行的第二个字符作为替换字符串
  • e 标志允许在替换部分中使用 Perl 代码

如果要替换的字符串可能匹配前两个字符,则:

$ echo 'oy 1 o 1 o 1' | perl -pe 's/o/substr($_,1,1)/ge if /^o/'
yy 1 y 1 y 1
$ echo 'oy 1 o 1 o 1' | perl -pe 's/..\Ko/substr($_,1,1)/ge if /^o/'
oy 1 y 1 y 1

我不确定在$_ 上使用substrs 命令修改$_ 是否危险。如果是这样,您可以使用以下替代方法:

perl -pe '$c=substr($_,1,1); s/x/$c/g if /^o/'

# courtesy @ikegami
perl -pe 's/x/$c/g if ($c) = /^o(.)/'

【讨论】:

  • perl -pe's/x/$c/g if ($c) = /^o(.)/' ip.txt
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 2020-10-23
  • 2014-08-30
相关资源
最近更新 更多