2017-11-26 16 views
0

私は何百万というデータを持っており、あるファイルから別のファイルに列の値を挿入しようとしています2。 file1がCSVファイルである場合( "|" パイプ区切る)が1つのファイル(CSV)の列の値を別のXML形式のファイルにコピーする

1.1.1.1|LM 
1.2.3.4|MV 
10.113.45.123|MN 

以下のようにデータを持っているとfile2は、XML形式のファイルベースである:ここで

<xml version="01"> 
     <raw_data> 
       <Add> 
         <value IP="" META=""></value> 
         <value IP="" META=""></value> 
         <value IP="" META=""></value> 
       </Add> 
     </raw_data> 
</xml> 

iはFILE2にFILE1のコラム第1回をコピーしたいです(以下のようにFILE2のMETAにIP)とコラム第2回:

<xml version="01"> 
     <raw_data> 
       <Add> 
         <value IP="1.1.1.1" META="LM"></value> 
         <value IP="1.2.3.4" META="MV"></value> 
         <value IP="10.113.45.123" META="MN"></value> 
       </Add> 
     </raw_data> 
    </xml> 

だから最終的に出力を上記のようにのように見えるはずです。 bashxmlstarletで複数の属性を更新するに

+0

それを修正する前に、XMLファイルの内容は何インプレイス編集の代わりにXML全体を書き直すことを検討しましたか? – yacc

+0

[私の編集のコメント](https://stackoverflow.com/revisions/47493633/2)は拒否された編集要求を指していました。 – Cyrus

答えて

2

declare -i c=1      # set integer attribute 
while IFS="|" read -r ip meta; do 
    xmlstarlet edit -L --omit-decl \ 
    --update "//raw_data/Add/value[$c]/@IP" --value "$ip" \ 
    --update "//raw_data/Add/value[$c]/@META" --value "$meta" file2.xml 
    c=c+1 
done < file1 

file2.xmlへの出力:

<xml version="01"> 
    <raw_data> 
    <Add> 
     <value IP="1.1.1.1" META="LM"/> 
     <value IP="1.2.3.4" META="MV"/> 
     <value IP="10.113.45.123" META="MN"/> 
    </Add> 
    </raw_data> 
</xml> 

更新変数$file内のすべての変更を実行するには:

をstdoutに10

出力:

<xml version="01"> 
    <raw_data> 
    <Add> 
     <value IP="1.1.1.1" META="LM"/> 
     <value IP="1.2.3.4" META="MV"/> 
     <value IP="10.113.45.123" META="MN"/> 
    </Add> 
    </raw_data> 
</xml> 

参照:xmlstarlet edit --help

+0

'xmlstarlet' - ジョブのための適切なツールで、それはとても見やすくなりました:) – sjsam

+1

小さな欠点は、file1の各行に対してfile2.xmlが書き直されることです。 – Cyrus

+0

Hmm。私は見て、オペアンプが何百万もの行を扱っていると考えると、重大なディスク使用量につながるでしょう。 – sjsam

0

、読み取り/書き込みをJSONに来るとき標準的なツールを使用するのは良いですあなたは間違いなくサイラスによって投稿答えを使用する必要がありますとxml。

あなたはまだ一般的なLinuxのコマンドを使用したい場合は、あなたがこのようなawkを使用して同じことを達成することができます

$ cat file 
1.1.1.1|LM 
1.2.3.4|MV 
10.113.45.123|MN 
$ awk -F\| 'BEGIN{printf "<xml version=\"01\">\n<raw_data>\n<Add>\n"} {printf "<value IP=\"%s\" META=\"%s\"></value>\n", $1, $2} END {printf "</Add>\n</raw_data>\n</xml>\n"}' file 
<xml version="01"> 
<raw_data> 
<Add> 
<value IP="1.1.1.1" META="LM"></value> 
<value IP="1.2.3.4" META="MV"></value> 
<value IP="10.113.45.123" META="MN"></value> 
</Add> 
</raw_data> 
</xml> 
$ 
0

xmlstartletが仕事をするために時間がかかる場合、あなたはperlを使用することを検討してみてくださいでしたが、I疑いの余地はありません。

# cat list 
1.1.1.1|LM 
1.2.3.4|MV 
10.113.45.123|MN 
# perl -ane 's/^([^|]+)\|([^\s]+)/<value IP="\1" META="\2"><\/value>/;\ 
    s/^/<xml version="01">\n<raw_data>\n<Add>\n/ if $. == 1;\ 
    s/$/\n<\/Add>\n<\/raw_data>\n<\/xml>/ if eof;\ 
    print' list 
<xml version="01"> 
<raw_data> 
<Add> 
<value IP="1.1.1.1" META="LM"></value> 
<value IP="1.2.3.4" META="MV"></value> 
<value IP="10.113.45.123" META="MN"></value> 
</Add> 
</raw_data> 
</xml> 


注:ないtidiest perlあなたがまだ得ることができます。改行をハードコードしないような推奨される方法に確認してください。しかし、私は現時点では少し怠惰です。また、使用して検討することもでき[ Tidy ]

+0

あなたはBEGIN/ENDを使ってawkの回答が投稿されたようなフィールドを使うことができます。正規表現は必要ありません:) – Sundeep

0

拡張awk + xmlstarlet協力:

awk -F'|' -v cmd='xmlstarlet ed -L -u "//Add/value[%d]/@IP" -v "%s" -u "//Add/value[%d]/@META" -v "%s" file2.xml' \ 
'system(sprintf(cmd, NR, $1, NR, $2))' file1.csv 

最終file2.xml内容:

<?xml version="1.0"?> 
<xml version="01"> 
    <raw_data> 
    <Add> 
     <value IP="1.1.1.1" META="LM"/> 
     <value IP="1.2.3.4" META="MV"/> 
     <value IP="10.113.45.123" META="MN"/> 
    </Add> 
    </raw_data> 
</xml> 
関連する問題