两个模式之间使用sed进行多次懒惰字符串替换

3

例子:

This (word1) is a test (word2) file.

我想要的:

This is a test file.

问题在于括号出现了多次,因此如果我使用:

sed 's/<.*>//g'

我可以得到一个错误的This file文件。


如果我想要替换两个相同模式之间的字符串怎么办?

例如:

WORD1 %WORD2% WORD3 => WORD1 WORD3

所以您想要删除括号内的所有文本? - fedorqui
没错。但是括号只是一个非常简单的例子,它也可以是多个符号,比如 #/要替换的内容/# 或 %要替换的内容%。 - Lobby2
1
请更新问题并提供更多细节。 - Wiktor Stribiżew
我刚刚发现\+可以使用,所以它不是纯BRE。这里可能有另一个重复的 - Wiktor Stribiżew
在字符类中不需要重复使用“%”符号。一个“[...]”结构只匹配方括号内指定的集合中的一个单一字符。 - Wiktor Stribiżew
显示剩余6条评论
1个回答

4
你只需要一个否定字符类[^<>]*,它将匹配除<>之外的任何字符。
sed 's/<[^<>]*>//g'

或者,如果你有圆括号,可以使用[^()]*(请注意,在BRE语法中,为了匹配文字(),不需要转义字符\):

sed 's/([^()]*)//g'

请看IDEONE演示

至于更新,您可以使用.*WORD1WORD3删除所有内容,但前提是只有一组WORD1WORD3演示):

echo "WORD1 %WORD2% WORD3" | sed 's/WORD1.*WORD3/WORD1 WORD3/g'

使用,无法使用前瞻(lookaheads)或懒惰量词来限制匹配到最左边的WORD3出现次数。如果你确定中间没有%符号,仍然可以使用否定字符类方法(演示):

echo "WORD1 %WORD2% WORD3" | sed 's/%[^%]*%//g'

一种通用解决方案是分几个步骤完成:

  • 使用未使用的字符<UC>)替换起始和结束定界符(我使用俄语字母,但应该是某些控制字符)
  • 使用否定字符类<UC1>[^<UC1><UC2>]*<UC2> 用所需的替换字符串进行替换
  • 恢复初始定界符。

这里有一个示例

#!/bin/bash
echo "WORD1 %WORD2% WORD3 some text WORD1 %WORD2% WORD3" | 
  sed 's/WORD1/й/g' |
  sed 's/WORD3/ч/g' |
  sed 's/й[^йч]*ч/й ч/g' |
  sed 's/й/WORD1/g' |
  sed 's/ч/WORD3/g' 
 // => WORD1 WORD3 some text WORD1 WORD3

我正在硬编码一个空格,但是可以根据需要进行调整。

现在我有另一个问题:如果我想要替换两个相同模式之间的字符串怎么办?比如 WORD1 %WORD2% WORD3 => WORD1 WORD3? - Lobby2
如果您的意思是您已经知道了 WORD1WORD3,并且需要删除它们之间的所有内容,那么这两者是不同的。也许您需要使用 这个 - Wiktor Stribiżew
这是一个非常常见的问题。如果您没有时间寻找好的重复内容,请不要回答。 - tripleee
您在正则表达式标签中拥有金徽章。您的答案不包含任何lookaround。 - tripleee
如果您正在引用OP的后续问题,则不,我会忽略它。如果OP有一个新问题,他们应该发布一个新问题或编辑当前问题。 - tripleee
@triplee:抱歉,我刚来这里,现在我知道该如何更新问题了:P - Lobby2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接