【问题标题】:SED: Deleting text between two strings, repeated across the lineSED:删除两个字符串之间的文本,跨行重复
【发布时间】:2015-01-19 10:03:58
【问题描述】:

问题是我希望使用 SED 删除一行中字符串之间的所有文本。我理解使用:sed -i 's/str1.*str2//' file.dat删除str1和str2之间的文字,包括str1和str2,但是我的行有str1和str2在行上重复了很多次,我想删除每一对之间的文字。我上面的尝试删除了 str1 的第一个实例和 str2 的最后一个实例之间的所有文本。希望能帮助您理解执行此操作的功能。

此外,我想在文件的所有行中重复此操作,并且不知道 str1、str2 对出现在每行上多少次。因人而异。

亲切的问候

附加编辑 - 希望不要进入火焰墙!

一个例子可能有用;到目前为止无法理解答案,对不起。

对于文件 example.dat 中的单行;

bla.bla.TextOfUnknownLength.bla.bla 1023=3 290=1 336=17 273=07:59:57.833 276=K 278=0 bla.bla.TextOfUnknownLength.bla.bla 1023=20 290=2 336=7 273=07:59:57.833 276=K 278=0 bla.bla.TextOfUnknownLength.bla.bla ...

我希望在所有情况下都从 1023= 删除到 278=(但不是 278= 之后的 0),1023= 和 278= 之间的文本可以在一行中出现多次并且长度未知。

文件中还有很多行,我想在所有行中运行它。

HS

【问题讨论】:

标签: bash sed


【解决方案1】:

sed -ri 's/(foo)(.*)(bar)/\1\3/g' between.file

解释。使用正则表达式-r 匹配行中之前、之间和之后的部分。然后只需使用带有前导反斜杠的 sed 内部替换变量替换前缀 \1 和后缀 \2

更新: 考虑between.file 包含以下内容。

foo---1---bar
foo---2---bar
foo---3---bar

然后上面的命令去掉foobar之间的内容,所以输出看起来像

foobar
foobar
foobar

这不是您想要的文件输出/更改吗?

更新:我认为awk 更合适 满足您的需求。

假设beween.file 包含以下几行

A foo---1---bar B foo---10--bar C 
A foo---2---bar D foo---20--bar E 
A foo---3---bar B foo---30---bar C 

这个脚本

#!/bin/bash
awk '{                            
                 all="";
                 for(i=0; i<=NF; i++) { 
                   if(!($i~/foo.*bar/)) { all=all" "$i; } 
                 };                            
                 print all;
               }' between.file

将产生以下输出

 A B C
 A D E
 A B C

您可以使用它来实现某种 DFA,以便在读取 1023= 并离开此读数 278= 时切换到特定状态。

将输出重定向到新文件或在文档中搜索 awk 以直接处理文件。希望这会有所帮助。

【讨论】:

  • 无需捕获(.*)。不过答案很好:)
  • 谢谢大家,只是为了清楚起见,并回复:我上面的例子; sed -ri 's/(1023=)(.*)(278=)/????/g' between.file 我在你的例子中用什么代替“\1”和“\3”来删除文字
  • 没有什么可以替代的。 \1\3 分别替换为 1023=278=,以 1023=278= 的方式打印/写入。
  • 再次感谢 Emil - 我看到这对线路有效 - 但删除了 FIRST 1023= 和 LAST 278= 之间的所有内容。该行有很多对,我正在尝试删除每对之间的文本,对于所有对。问候。 HS
  • for between.file 包含以下内容; A foo---1---bar X foo---10--bar Y A foo---2---bar X foo---20--bar Y A foo---3---bar X foo ---30---bar Y 我正在寻找结果文件; A X Y A X Y A X Y 字符串“foo--sometext---bar”在一行中重复了很多次
【解决方案2】:

只需在 sed 末尾添加 g

sed -i 's/str1.*str2//g' file.dat 
  • g 意思是:对于当前缓冲区的每一次出现,默认情况下这是当前行。
  • sed 默认一次工作 1 行,然后在操作结束时继续下一行。

备注:

  • 如果 str1 和 str2 不在同一行,则两者之间没有变化
  • str1 和 str2 是模式的一部分,因此有时需要转义一些特殊字符(例如 (,{,[,\,&amp;,^,.,..,具体取决于所需的行为。

【讨论】:

    【解决方案3】:

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

    sed -r ':a;s/([^\n]*)(foo)[^\n]+(bar)/\1\n\2\3/;ta;s/\n//g' file
    

    使用贪婪、唯一分隔符和循环删除foobar 之间的字符。贪婪通过该行向后工作,并且分隔符阻止已处理的行部分再次被处理。该循环删除foobar 的一次或多次出现。

    【讨论】:

      最近更新 更多