【问题标题】:Perl regex substitution: Substitute particular string, if another particular string is not on the same linePerl 正则表达式替换:替换特定字符串,如果另一个特定字符串不在同一行上
【发布时间】:2014-05-25 15:38:14
【问题描述】:

我有这样的文字:

Hi
... OK ... Replace ...
... BAD ... Replace ...
Hi

当且仅当“BAD”不在同一行的任何位置时,我想用“Done”替换所有“Replace”字符串。所以唯一应该修改的行是我给出的示例中的第二行。我正在努力做到这一点,我尝试了以下不起作用:

perl -i'' -pe 's/^(?!BAD)Replace/$1Done/g' TEST

这可以像我想要做的那样在一个表达式中完成吗?

【问题讨论】:

  • BAD 必须在Replace 字符串之前还是可以在行中的任何位置?
  • 两者都可以,因为永远不会出现 BAD 出现在 Replace 之后的情况。

标签: regex perl regex-negation substitution


【解决方案1】:

您试图在单个正则表达式中做太多事情。这更直接,更容易正确

perl -pe "s/Replace/Done/ unless /BAD/" mydata

输出

Hi
... OK ... Done ...
... BAD ... Replace ...
Hi

【讨论】:

  • 太好了,谢谢。这似乎完美无缺。这是否意味着 Perl 会分别查看每一行?
  • 我只需要添加 g 修饰符来替换多个匹配项。
  • Perl 的命令行选项 -p 在您的代码周围放置了一个 while (<>) { ...; print } 循环,所以是的,在这种情况下,它将代码分别应用于每一行
  • 啊,好吧。我不明白您的数据中可能有多个Replace 字符串。如果可能的话,它总是可以帮助您发布您的真实数据
  • 嗯?当然,这仅在进行替换之前检查单词 BAD 是否不在同一行 - 但 OP 明确表示 BAD 可能不会在之前发生......
【解决方案2】:

如果线上只有一个Replace,你可以使用类似

s/^(?!.*BAD.*Replace)(.*)Replace/$1Done/

否定的前瞻将检查此行上的Replace 之前没有任何BAD。如果是这样,请将Replace 替换为Done

【讨论】:

  • /g/m 修饰符在这里都没有任何用处
  • 啊,显然从 OP 所说的来看,一行中可能有多个 Replace 字符串,所以我对 /g 的看法是错误的。我的道歉
  • @Borodin:这个正则表达式只捕获Replace 的第一次出现,所以你的评论实际上仍然相关
【解决方案3】:

如果您的意思是这样,您可以使用 sed 执行此操作:

sed -i -e '/BAD/!s/Replace/Done/' TEST

【讨论】:

  • 如果您允许 BAD 在替换之前或之后出现,sed 解决方案会更容易。
猜你喜欢
  • 1970-01-01
  • 2021-12-19
  • 2013-02-16
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
  • 1970-01-01
  • 2019-09-07
相关资源
最近更新 更多