【问题标题】:Replace string between words multiple times in a file在文件中多次替换单词之间的字符串
【发布时间】:2019-02-12 07:02:00
【问题描述】:

我正在尝试使用以下命令替换文件中两个字符串之间的字符串。文件中可能有任意数量的此类模式。这只是一个例子。

sed 's/word1.*word2/word1/' 1.txt 

在我正在测试的示例源文件中,有两个例子是“word1”后跟“word2”。 1.txt文件的内容

word1---sjdkkdkjdk---word2 I want this text----word1---jhfnkfnsjkdnf----word2 I need this also

结果如下。

word1 I need this also

预期输出:

 word1 I want this text----word1 I need this also

有人可以帮我解决这个问题吗?

我查看了其他堆栈溢出问卷,但他们讨论了仅替换模式的一个实例。

【问题讨论】:

  • @jww 这不是重复的。 OP 有一个不同的问题。
  • 您应该在示例中包含类似x word1 foo word1 bar word2 y 这样的案例,以便我们可以查看您是否希望其输出为x world1 y(最外层匹配)或x word1 foo word1 y(最内层匹配) ) 或其他东西。
  • @jww 这是另一个问题。

标签: linux awk sed


【解决方案1】:

正则表达式是贪心的——它们匹配最长的字符串,所以从第一个“word1”到最后一个“word2”的所有内容。不确定是否有任何版本的 sed 支持非贪婪的正则表达式......不过,您可以只使用 perl,它可以:

perl -pe 's/word1.*?word2/word1/g' 1.txt

应该可以解决问题。 ? 将先前的 * 的含义从“只要其余模式匹配就尽可能多地匹配”变为“只要其余模式匹配就尽可能少地匹配”。

【讨论】:

  • 感谢肖恩的建议。让我试试这个。
【解决方案2】:
$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/word1/{/g; s/word2/}/g; s/{[^{}]*}/word1/g; s/}/word2/g; s/{/word1/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
word1 I want this text----word1 I need this also

它很长,看起来很复杂,但它是一种经常使用的技术,实际上只是一系列简单的步骤,可以将word1 稳健地转换为{word2},所以你正在处理在实际替换 s/{[^{}]*}/word1/g 中使用字符而不是字符串,因此可以使用否定括号表达式来避免贪婪的正则表达式占用过多的行。

请参阅https://stackoverflow.com/a/35708616/1745001 以了解有关此处使用的一般方法的更多信息,该方法能够将字符串转换为在实际工作发生时无法出现在输入中的字符,然后再恢复它们。

【讨论】:

  • 让我试试这个 Ed.
  • 它适用于大多数情况,但当 word1 是 's3a://' 而 word2 是 '@' 时,它对我不起作用。我也转义了“/”字符。它以某种方式添加了一个额外的“A”。这是我尝试过的命令供您参考。不过,肖恩的上述回答对我有用。非常感谢您的帮助并帮助我了解 Ed。赞成。
  • 对,想想它在做什么。当您想要创建不存在的字符以将目标字符串映射到时,您不能让这些字符串之一实际上是(或包含)您尝试用于该目的的字符之一。在这种情况下选择不同的字符。同样,如果您的单词包含/,那么不要使用/ 作为sed 分隔符,使用其他字符。
【解决方案3】:

如果一行中只有两个 word1-word2 模式的实例,这应该可以:

sed 's/\(word1\).*word2\(.*\)\(word1\).*word2\(.*\)/\1\2\3\4/' 1.txt

我抓住我们想要保留在转义括号内的部分 \( 和 \) 然后我可以将这些部分称为 \1 \2 等等。

【讨论】:

  • 不是大卫,我提供的是样本数据。该文件可能包含任意数量的事件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 2022-01-17
  • 1970-01-01
  • 2016-11-24
  • 1970-01-01
相关资源
最近更新 更多