【问题标题】:How to extract everything between two patterns (using sed?)?如何提取两种模式之间的所有内容(使用 sed?)?
【发布时间】:2020-05-08 03:19:05
【问题描述】:

我正在运行一个 curl 命令(加上一个 grep),我想从输出中提取两个模式之间的所有内容。

这是 curl(和 grep)的示例输出:

                                 Dload  Upload   Total   Spent    Left  Speed
100 15848    0 15848    0     0   708k      0 --:--:-- --:--:-- --:--:--  736k
</message><refDesc>PULL Task 8c4d1a50-3e05-4b58-8d1a-503e057b586d 4_Place_All_Users_In_Inactive</refDesc><refKey>8c4d1a50-3e05-4b58-8d1a-503e057b586d</refKey><status>SUCCESS</status></syncope21:exec><syncope21:exec xmlns:syncope21="http://syncope.apache.org/2.1"><end>2020-01-22T01:13:44.512Z</end><start>2020-01-22T01:13:44.506Z</start><jobType>TASK</jobType><key>40e64a39-47e7-4428-a64a-3947e7c4286b</key><message>Users [created/failures]: 0/0 [updated/failures]: 0/0 [deleted/failures]: 0/0 [no operation/ignored]: 0/0

我想提取 &lt;/message&gt;&lt;/start&gt; 之间的所有内容,例如,从上面,我想要:

&lt;/message&gt;&lt;refDesc&gt;PULL Task 8c4d1a50-3e05-4b58-8d1a-503e057b586d 4_Place_All_Users_In_Inactive&lt;/refDesc&gt;&lt;refKey&gt;8c4d1a50-3e05-4b58-8d1a-503e057b586d&lt;/refKey&gt;&lt;status&gt;SUCCESS&lt;/status&gt;&lt;/syncope21:exec&gt;&lt;syncope21:exec xmlns:syncope21="http://syncope.apache.org/2.1"&gt;&lt;end&gt;2020-01-22T01:13:44.512Z&lt;/end&gt;&lt;start&gt;2020-01-22T01:13:44.506Z&lt;/start&gt;

我尝试了以下方法:

curl -X GET ...." | grep xxxxxxx | sed -n -e '/&lt;\/message&gt;/,/&lt;\/start&gt;/p'

但它似乎没有工作(它似乎是返回整个输出,而不是提取。

谁能告诉我该怎么做?

谢谢!

吉姆

【问题讨论】:

    标签: regex sed


    【解决方案1】:

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

    sed '/\n/!{s/<\/message>/\n&/;s/<\/start>/&\n/};/^<\/message>/P;D' file
    

    如果一行尚未修改,请在&lt;/message&gt; 之前和&lt;/start&gt; 之后插入一个换行符,并仅打印该行的那一部分。

    【讨论】:

      【解决方案2】:

      您能否在下面使用GNU sed

      sed -E -n 's#(^&lt;/message&gt;.*&lt;/start&gt;).*#\1#p'

      所以,基本上,你的命令看起来像:

      curl -X GET ...." | grep xxxxxxx | sed -E -n 's#(^&lt;/message&gt;.*&lt;/start&gt;).*#\1#p'

      【讨论】:

      • 啊 - 好的,我想我看到了问题(我的错误)。我没有意识到这两行(格式相似但信息不同)。所以你的 sed 命令确实有效,但它正在处理两行(看起来有些情况甚至超过 2 行)。如果我可能会问,我如何更改 sed 以便它只处理第一行并输出?
      • @user555303:好吧。在这种情况下,您将sed 命令传送到|head -n 1 以获取输出的第一行。此外,您可以使用sedcurl -X GET ...." | sed -E -n '/xxxxxxx/ s#(^&lt;/message&gt;.*&lt;/start&gt;).*#\1#p' |head -n 1 搜索所需的字符串,而不是使用grep
      【解决方案3】:

      awk 解决方案:如果 Input_file 中存在数据,请尝试以下操作。

      awk 'match($0,/<\/message>.*<start>/){print substr($0,RSTART,RLENGTH)}' Input_file
      

      或与curl 一起使用:

      curl -X GET ...." | awk '{gsub(/\r/,"")} match($0,/<\/message>.*<start>/){print substr($0,RSTART,RLENGTH)}'
      


      sed 解决方案: 或使用 GNU sed-z 选项:

      sed -z 's/.*\(<\/message>.*<start>\).*/\1\n/' Input_file
      

      curl + sed

      curl -X GET ...." | sed -z 's/\r//g;s/.*\(<\/message>.*<start>\).*/\1\n/'
      

      显示的示例输出如下。

      &lt;/message&gt;&lt;refDesc&gt;PULL Task 8c4d1a50-3e05-4b58-8d1a-503e057b586d 4_Place_All_Users_In_Inactive&lt;/refDesc&gt;&lt;refKey&gt;8c4d1a50-3e05-4b58-8d1a-503e057b586d&lt;/refKey&gt;&lt;status&gt;SUCCESS&lt;/status&gt;&lt;/syncope21:exec&gt;&lt;syncope21:exec xmlns:syncope21="http://syncope.apache.org/2.1"&gt;&lt;end&gt;2020-01-22T01:13:44.512Z&lt;/end&gt;&lt;start&gt;

      【讨论】:

      • 你的最后一个(curl * sed)接近了,但它没有提取&lt;start&gt;元素的值?吉姆
      • @user555303,请问这些解决方案是否对您有帮助?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-29
      • 2020-01-09
      • 1970-01-01
      • 2022-10-24
      • 1970-01-01
      相关资源
      最近更新 更多