web-dev-qa-db-ja.com

単純なXMLファイルからのデータの抽出

私は内容を含むXMLファイルを持っています:

<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>

<job..></job>タグの内容(この場合はprogrammin)を抽出する方法が必要です。これは、grep/sed/awkを使用して、Linuxコマンドプロンプトで実行する必要があります。

39
Zacky112

あなたは本当にする必要がありますこれらのツールのみを使用しますか? XML処理用に設計されていないため、ほとんどの場合問題なく動作するものを取得することは可能ですが、エンコード、改行などのEdgeの場合は失敗します。

Xml_grepをお勧めします。

xml_grep 'job' jobs.xml --text_only

出力が得られます:

programming

Ubuntu/debianでは、xml_grepはxml-twig-toolsパッケージに含まれています。

63
amarillion
 grep '<job' file_name | cut -f2 -d">"|cut -f1 -d"<"
12
Vijay

Xmlstarletの使用:

echo '<job xmlns="http://www.sample.com/">programming</job>' | \
   xmlstarlet sel -N var="http://www.sample.com/" -t -m "//var:job" -v '.'
9
lmxy

XMLでの行および正規表現ベースの解析は使用しないでください。それは悪い考えです。異なるフォーマットのセマンティック上同一のXMLを使用できますが、正規表現と行ベースの解析では単純に対応できません。

単項タグや可変行の折り返しなど-これらのスニペットは同じことを「言います」:

<root>
  <sometag val1="fish" val2="carrot" val3="narf"></sometag>
</root>


<root>
  <sometag
      val1="fish"
      val2="carrot"
      val3="narf"></sometag>
</root>

<root
><sometag
val1="fish"
val2="carrot"
val3="narf"
></sometag></root>

<root><sometag val1="fish" val2="carrot" val3="narf"/></root>

うまくいけば、これが正規表現/行ベースのパーサーの作成が難しい理由を明らかにすることを願っています。幸いなことに、あなたはする必要はありません。多くのスクリプト言語には、少なくとも1つ、時にはより多くのパーサーオプションがあります。

以前のポスターが示唆したように、xml_grepが利用可能です。これは、実際には XML::Twig Perlライブラリに基づいたツールです。ただし、「xpath式」を使用して何かを見つけ、ドキュメント構造、属性、および「コンテンツ」を区別します。

例えば。:

xml_grep 'job' jobs.xml --text_only

ただし、より良い回答を得るために、ソースデータに基づいた「独自のロール」の例をいくつか示します。

最初の方法:

特定のタイプの要素をキャッチしてそれらに作用するtwig handlersを使用します。この方法で行う利点は、XMLを「そのまま」解析し、必要に応じて飛行中にXMLを変更できることです。これは、purgeまたはflushを使用して大きなファイルを操作しているときに「処理済み」XMLを破棄する場合に特に便利です。

#!/usr/bin/Perl

use strict;
use warnings;

use XML::Twig;

XML::Twig->new(
    twig_handlers => {
        'job' => sub { print $_ ->text }
    }
    )->parse( <> );

<>を使用して入力を取得し(入力、またはコマンドライン./myscript somefile.xmlで指定)、それを処理します。各job要素は、関連するテキストを抽出して印刷します。 (print $_ -> text,"\n"で改行を挿入したい場合があります)。

「job」要素で一致するため、ネストされたジョブ要素でも一致します。

<job>programming
    <job>anotherjob</job>
</job>

2回一致しますが、出力の一部も2回印刷します。ただし、必要に応じて/jobで一致させることもできます。便利-これにより、例えば要素を印刷して削除するか、XML構造を変更する要素をコピーして貼り付けます。

または、最初に解析し、構造に基づいて「印刷」します:

my $twig = XML::Twig->new( )->parse( <> );
print $twig -> root -> text;

jobがルート要素であるため、必要なのはそのテキストを印刷することだけです。

しかし、もう少し見識があり、jobまたは/jobを探して、代わりに具体的に出力します。

my $twig = XML::Twig->new( )->parse( <> );
print $twig -> findnodes('/job',0)->text;

XML::Twigs pretty_printオプションを使用して、XMLも再フォーマットできます。

XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( <> ) -> print;

さまざまな出力形式のオプションがありますが、よりシンプルなXML(あなたのような)の場合、ほとんどが非常によく似ています。

9
Sobrique

awkを使用するだけで、他の外部ツールは必要ありません。必要なタグがマルチタインに表示されている場合、以下が機能します。

$ cat file
test
<job xmlns="http://www.sample.com/">programming</job>
<job xmlns="http://www.sample.com/">
programming</job>

$ awk -vRS="</job>" '{gsub(/.*<job.*>/,"");print}' file
programming

programming
8
ghostdog74

同じ行を想定して、stdinからの入力:

sed -ne '/<\/job>/ { s/<[^>]*>\(.*\)<\/job>/\1/; p }'

ノート: -nは、すべての出力を自動的に停止します。 -eは、それがワンライナー(スクリプトである)であることを意味します/<\/job>はgrepのように機能します。 sは、opentag +属性と終了タグを取り除きます。 ;は新しいステートメントです。 pプリント; {}は、grepを両方のステートメントに1つとして適用します。

5
13ren

sedコマンドを使用:

例:

$ cat file.xml
<note>
        <to>Tove</to>
                <from>Jani</from>
                <heading>Reminder</heading>
        <body>Don't forget me this weekend!</body>
</note>

$ cat file.xml | sed -ne '/<heading>/s#\s*<[^>]*>\s*##gp'
Reminder

説明:

cat file.xml | sed -ne '/<pattern_to_find>/s#\s*<[^>]*>\s*##gp'

n-すべての行の出力を抑制します
e-スクリプト

/<pattern_to_find>/-指定されたパターンを含む行を検索します。例:<heading>

次に、置換部分s///pを使用して、読みやすいように/#に置き換えた目的の値以外のすべてを削除します。

s#\s*<[^>]*>\s*##gp
\s*-存在する場合は空白を含む(最後に同じ)
<[^>]*>は、貪欲でない正規表現の代替原因として<xml_tag>を表します<.*?>はsedでは機能しません
g-すべてを置き換えます。 xml </xml_tag>タグを閉じる

3
vldbnc

ショーに少し遅れました。

xmlcutty XMLからノードを切り取ります:

$ cat file.xml
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
<job xmlns="http://www.sample.com/">designing</job>
<job xmlns="http://www.sample.com/">managing</job>
<job xmlns="http://www.sample.com/">teaching</job>

path引数は、切り取る要素のパスを指定します。この場合、タグにはまったく関心がないため、タグの名前を\nに変更し、Niceリストを取得します。

$ xmlcutty -path /job -rename '\n' file.xml
programming
designing
managing
teaching

XMLは、最初は有効ではありませんでした(ルート要素なし)。 xmlcuttyは、わずかに壊れたXMLでも機能します。

0
miku

どうですか:

cat a.xml | grep '<job' | cut -d '>' -f 2 | cut -d '<' -f 1
0
codaddict