将一条长线作为多条线管道

时间:2011-07-02 14:52:25

标签: bash shell scripting awk zsh

假设我有一堆XML文件,其中不包含换行符,但基本上包含一长串记录,由</record><record>

分隔

如果分隔符为</record>\n<record>,我可以执行cat *.xml | grep xyz | wc -l之类的操作来计算感兴趣的记录实例,因为cat会每行发出一个记录。

有没有办法写SOMETHING *.xml | grep xyz | wc -l SOMETHING每行可以流出一条记录?我尝试使用awk,但无法找到避免将整个文件流式传输到内存中的方法。

希望问题很清楚:)

4 个答案:

答案 0 :(得分:5)

这有点难看,但它有效:

sed 's|</record>|</record>\
|g' *.xml | grep xyz | wc -l

(是的,我知道我可以缩短一点,但只是以清晰为代价。)

答案 1 :(得分:2)

如果您的记录正文中没有</>这样的字符,那么您可以试试这个:

grep -E -o 'SEARCH_STRING[^<]*</record>' *.xml| wc -l

grep -E -o 'SEARCH_STRING[^/]*/record>' *.xml| wc -l

grep -E -o 'SEARCH_STRING[^>]*>' *.xml| wc -l

答案 2 :(得分:2)

以下是使用 xsltproc grep wc 的不同方法。警告:我是XSL的新手所以我可能很危险:-)。这是我的count_records.xsl文件:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text" />      <!-- Output text, not XML -->
  <xsl:template match="record">     <!-- Search for "record" node -->
    <xsl:value-of select="text()"/> <!-- Output: contents of node record -->
    <xsl:text>                      <!-- Output: a new line -->
    </xsl:text>
  </xsl:template>

</xsl:stylesheet>

在我的Mac上,我找到了一个名为 xsltproc 的命令行工具,该工具读取XSL文件中的指令,处理XML文件。所以命令是:

xsltproc count_records.xsl *.xml | grep SEARCH_STRING | wc -l
  • xsltproc 命令显示每个节点中的文本,一次一行
  • grep 命令会过滤掉您感兴趣的文字
  • 最后, wc 命令产生计数

答案 3 :(得分:1)

您也可以尝试使用xmlstarlet gig大小的文件:

# cf. http://niftybits.wordpress.com/2008/03/27/working-with-huge-xml-files-tools-of-the-trade/

xmlstarlet sel -T -t -v "count(//record[contains(normalize-space(text()),'xyz')])" -n *.xml | 
    awk '{n+=$1} END {print n}'

xmlstarlet sel -T -t -v "count(//record[contains(normalize-space(text()),'xyz')])" -n *.xml | 
    paste -s -d '+' /dev/stdin | bc