如何用sed一次性提取令牌之间的多个模式?

时间:2018-05-23 09:19:57

标签: xml bash sed xmlstarlet

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

blahblah token substring token something else token substring2 token

整个文件只包含一条长行。

我想用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

1 个答案:

答案 0 :(得分:3)

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

您可以使用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