2011-07-02 9 views
3

は、区切り文字が</record>\n<record>だったら私が行うことができるだろう</record><record>パイプを複数行として一の長い行が

で区切られ、私は改行を含まないXMLファイルの束を持っていると言うが、基本的には、レコードの長いリストが含まれていますcatは1行に1つのレコードを出力するため、cat *.xml | grep xyz | wc -lのようなもので、対象のレコードのインスタンスを数えます。

SOMETHING *.xml | grep xyz | wc -lを書く方法はありますか?SOMETHINGはレコードを1行に1つストリーム配信できますか?私はこのためにawkを使ってみましたが、ファイル全体をメモリにストリーミングするのを避ける方法を見つけることができませんでした。

うまくいけば、問題は、あなたのレコード体が<または/または>ようには文字を持っていない場合、あなたはこの試みることが十分に明確:)

答えて

5

これは少し醜いですが、それは動作します:

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

(はい、私は唯一の明確さのコストで、私はそれが少し短く作ることができます知っている。)

+1

これは私の 'awk'よりはるかに高速ですが、' sed'はファイル全体をメモリに読み込みます。もっと「ストリーミング」バージョンはありますか? XMLファイルのサイズが大きければどうなるでしょうか? – nicolaskruchten

+2

@nicolas:Perlと 'read'関数(' <> '演算子ではない)を使って、ファイルのチャンクを読み込み、改行を挿入し、書き出すことができます。トリックビットは、ブロック13が ' 'シーケンスの途中で終了するのに不利な場合に、次の部分で処理するために後続コンテキストを保持することを保証することです。特にブロック13が '<'や ''または 'record>'を開始した場合にそれらの文字を残しておく必要があることに注意してください。この種の分割を行うための標準的なユーティリティはないと思います。ほとんどのUnixユーティリティは回線上で動作します。 –

+0

少し読みやすく: 'sed $ 's | |&\ n | g '... ' - bashの構文[' $' ''](http://www.gnu.org/software/bash/manual/bashref.html#ANSI_002dC-Quoting)を使用します。文字列のエスケープシーケンスを有効にします。 –

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 
+0

OK、これは非常にいいです、そしてレコードをgrepをについての私の具体的な問題に対処し、私は長いラインを離れて壊し、発光により一般的な解決策を探していましたパイプを一度に1つずつ、別の答えに「sed」バージョンを入れてください:)まだメモリにすべてをロードしていないものを探しています! – nicolaskruchten

+0

また、他の答えの 'sed'バージョンははるかに高速ですが、私はなぜか分かりません... – nicolaskruchten

2

ここれますxsltproc,grepおよびwcを使用する別の方法です。警告:私はXSLの初心者ですので危険です:-)。ここに私のcount_records.xslファイルです:私のMac上で

<?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> 

、私はプロセスのXMLファイル、XSLファイルからの指示を読んでxsltprocのと呼ばれるコマンドラインツールを見つけました。だから、コマンドは次のようになります

xsltproc count_records.xsl *.xml | grep SEARCH_STRING | wc -l 
  • xsltprocのコマンドは、各ノード内のテキスト、1行ずつ
  • のgrepコマンドフィルタアウトあなたが
  • に興味のあるテキストを表示します
  • は最後に、WCコマンドは、カウントを生成
1

あなたかもしれませんLSOギグサイズのファイルのためのxmlstarletを試してみてください。

# 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 
関連する問題