如何使用 sed 一次提取标记之间的多个模式?

Posted

技术标签:

【中文标题】如何使用 sed 一次提取标记之间的多个模式?【英文标题】:How to extract multiple patterns between tokens at once with sed? 【发布时间】:2018-11-02 05:09:48 【问题描述】:

假设我有一个名为 inputFile 的文件,看起来像这样:

blahblah token substring token something else token substring2 token

整个文件只包含 1 长行。

我想用 sed (substring,substring2) 提取标记之间的子字符串。

此时我有:

[sed "s/^.* \?token\(.* \)token.* \?/\1/"][1] inputFile > outputFile

我根据这些问题尝试这样做,但不幸的是它只返回最后一个子字符串

Extract lines between 2 tokens in a text file using bash

How to replace multiple patterns at once with sed?

How to select lines between two patterns?

有解释的答案会很棒。

更新 实际输入代码:

<archive><message id="0"><receiver>apr</receiver><sender>gtr</sender><text>52333</text><sendTime>554</sendTime><deliveryTime>765</deliveryTime></message><message id="0"><receiver>apr</receiver><sender>gtr</sender><text>4332</text><sendTime>764</sendTime><deliveryTime>922</deliveryTime></message></archive>

预期输出:

apr gtr 52333
apr gtr 4332

【问题讨论】:

开头不是缺少&lt;archive&gt;吗? 你必须添加在什么基础上输出到达..另外,如果它是有效的 xml,使用像 xmlstarlet 这样的 xml 解析器或带有 xml 模块的编程语言.. @kvantour 是的,确实 @MariuszBakun 我已经用提供请求输出的xmlstarlet cmd 更新了我的答案。 【参考方案1】:

问题是sed 是贪婪的,所以如果你添加全局标志(g),上面的命令只会返回substring2

您可以为此使用awk,将字段分隔符FS 重新定义为字符串token。这样你的字符串就在偶数场位置:

$ echo "blahblah token substring token something else token substring2 token"  | \
  awk -F 'token' 'for(i=2;i<=NF;i+=2) print $i'
 substring 
 substring2

更新:

如果您的输入是一个 xml 文件,您可能想要这样做:

<archive>
   <message id="0">
       <receiver>apr</receiver>
       <sender>gtr</sender>
       <text>52333</text>
       <sendTime>554</sendTime>
       <deliveryTime>765</deliveryTime>
   </message>
   <message id="0">
       <receiver>apr</receiver>
       <sender>gtr</sender>
       <text>4332</text>
       <sendTime>764</sendTime>
       <deliveryTime>922</deliveryTime>
   </message>
 </archive>" 

通向 cmd :

xmlstarlet sel -t -m '//message' -v receiver -o " " -v sender -o " " -v text -n <file>

哪个输出

apr gtr 52333
apr gtr 4332

【讨论】:

以上是关于如何使用 sed 一次提取标记之间的多个模式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在两个相同的标记模式之间获取特定数据

如何使用 sed/grep 提取两个单词之间的文本?

在两个标记之间提取文本并替换字符

sed 中如何替换换行符

如何在R中提取带有特殊字符的模式之间的字符串[重复]

Linux的shell匹配模式之间提取子