簡體   English   中英

bash:使用 awk 或 sed 在引號之間提取屬性值(GNU grep 不是一個選項)

[英]bash: extract an attribute value between quotes using awk or sed(GNU grep is not an option)

我有一個包含如下數據的 xml 文件

<temp>
<a="something" total="50" b="something" total="0" c="something" total="20">
</temp>

我需要獲得總的第一個值,即 50,但我的 sed 解決方案給出了總的最后一次出現的值,即 20

sed -n 's/.*total="\([^"]*\).*/\1/p' temp.xml

輸出:20

所需輸出:50

我很感激你的幫助。 謝謝

您或許應該使用 xml 感知工具,但 grep 可以輕松處理此問題。

grep -Pom1 '(?<=total=")[^"]+' file | head -1
50

這會在第一個匹配的行上找到所有的總屬性值並獲取其中的第一個。

缺乏對正則表達式功能的了解,您可以回退到

$ grep -Eo 'total="[^"]+"' file | awk -F\" '{print $2; exit}'

50

示例數據文件:

$ cat my.xml
<temp>
<a="something" total="50" b="something" total="0" c="something" total="20">
</temp>

以及基於有限數據樣本和檢索第一個total唯一要求的快速awk解決方案:

$ awk -F'"' '/ total=/ { print $4}' my.xml
50
  • -F'"' : 將(輸入)字段分隔符定義為雙引號
  • / total=/ :只對包含字符串“total=”的行感興趣,然后...
  • print $4 :打印第 4 個字段

你可以試試

cut -sd '"' -f 4 my.xml

以下將打印文件中所有a元素的total屬性,一行:

xmlstarlet sel -t -m '//a[@total]' -v ./@total -n <your-file.xml

如果您沒有 XMLStarlet,則可以使用xsltproc (幾乎隨處可用)來完成此操作。 給定以下 xslt 文件(作為xmlstarlet sel -C -t -m '//a[@total]' -v ./@total -n輸出生成):

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
  <xsl:output omit-xml-declaration="yes" indent="no"/>
  <xsl:template match="/">
    <xsl:for-each select="//a[@total]">
      <xsl:call-template name="value-of-template">
        <xsl:with-param name="select" select="./@total"/>
      </xsl:call-template>
      <xsl:value-of select="'&#10;'"/>
    </xsl:for-each>
  </xsl:template>
  <xsl:template name="value-of-template">
    <xsl:param name="select"/>
    <xsl:value-of select="$select"/>
    <xsl:for-each select="exslt:node-set($select)[position()&gt;1]">
      <xsl:value-of select="'&#10;'"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

...你可以運行:

xsltproc extract-totals.xslt your-file.xml

正確的方法是使用 xml/html 解析器,如xmllint和/或xmlstarlet

xmllint解決方案:

xmllint --html --xpath "string(//a/@total)" temp.xml 2>/dev/null
50

sed不支持非貪婪匹配。 摘自這里

在 sed 中獲得非貪婪匹配的技巧是匹配除終止匹配的字符之外的所有字符。

所以你的解決方案是:

sed -n 's/.[^ ]* total="\([^"]*\).*/\1/p' temp.xml

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM