grep

grep

私は周りを見回しましたが、私と同じ問題を抱えている人を見つけることができませんでした。

次のXMLファイルがあります。

<ID>1</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed><ID>2</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed><ID>3</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed><ID>4</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed>

デフォルトでは、改行なしで1行に多くのデータがあります。特定の<ID>タグ(<ID> 2など)と次の</dateAccessed>タグの間の情報を抽出する必要があります(タグをそのまま保存することをお勧めします)。特定のIDと下記の関連データを確認できるファイルが50個ほどあります。私はこれが標準ではなく、ネストがないことを知っています。

最初はgrepとsedを使ってこれを試しましたが、ファイル全体が返されて奇妙に見えました。テキストファイルとして処理できませんか?

編集する:

フォーマッタが<と>のテキストを削除したことを知らなかったので、今朝私の質問をもう一度読んだ後、私は全く違うことを求めていることに気づきました。 TL;DR ID タグと次の終了 DateAccessed タグの間に特定の値が必要です。同じ開始タグと終了タグの間、つまりIDと/ IDの間にない

だから私は次のようなものを得ることができます:

<ID>2</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed>

答え1

コメントで指摘したように、データは正しい形式のXMLではなく、文書の構造が何であるかは完全には明確ではありません。たとえば、サンプルデータで判断すると、入れ子になった要素がないように見えます。これは本当に本当ですか? ?

これを念頭に置いて、次を使用するPythonスクリプトがあります。美しいスープ4目的のタスクを実行するためにライブラリを解析します(つまり、与えられたサンプル入力データに必要な出力データを生成します)。

#!/usr/bin/env python
# coding: ascii
"""extract.py

Extract everything between two XML tags
in a (possibly poorly formed) XML document."""

from bs4 import BeautifulSoup
import sys

# Set the opening tag name and value
opening_name = "ID"
opening_text = "2"

# Set the closing tag name
closing_name = "dateAccessed"

# Get the XML data from a file and instantiate a BeautifulSoup parser
# We add a root node because the input data is missing a root
with open(sys.argv[1], 'r') as xmlfile:
    xmldoc = "<root>" + xmlfile.read() + "</root>"
    soup = BeautifulSoup(xmldoc, 'xml')

# Iterate through the elements of the XML data and collect
# all of the elements inbetween the opening and closing tags
elements = []
match = False
for e in soup.find_all():
    if match is True:
        elements.append(str(e))
        if e.name==closing_name:
            break
    else:
        try:
            if e.name==opening_name and e.text==opening_text:
                match = True
                elements.append(str(e))
        except AttributeError:
            pass

# Output the results on a single line
print("".join(elements))

次のように実行できます。

python extract.py data.xml

与えられたサンプルデータの場合:

<ID>1</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed><ID>2</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed><ID>3</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed><ID>4</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed>

次の出力が生成されます。

<ID>2</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed>

答え2

XML文書に実際にルートタグがあると仮定すると(あなたのXMLにはルートタグがないためフォーマットが正しくありません)、次のようにXMLstarletを使用できます。

xmlstarlet sel -t -m '//ID[. = 2]' \
    -c . -c './following-sibling::*[position()<5]' -nl file.xml

与えられたデータ(<root>最初と</root>最後に挿入するように変更されています)に対して、以下を返します。

<ID>2</ID><data>asdf</data><data2>asdf</data2><dataX>asdf</dataX><dateAccessed>somedate</dateAccessed>

XMLstarletクエリは、コンテンツがID2-m '//ID[. = 2]'のすべてのノードを選択します。これらの各ノード(与えられたデータには1つしかありません)に対して、ノード自体のコピー(-c .)と次の5つの兄弟ノードのコピー()を返し、-c './following-sibling::*[position()<5]'改行文字()を挿入して-nl出力を終了します。

開く<root>タグと閉じるタグは、ドキュメント自体に挿入するか、次のようにXMLstarletに渡すことができます。

{ echo '<root>'; cat file.xml; echo '</root>'; } |
xmlstarlet sel -t -m '//ID[. = 2]' \
    -c . -c './following-sibling::*[position()<5]' -nl

答え3

grep

grep -oE '<data>[^<]*</data>' yourxmlfile

吹く

tag='data'
tL="<$tag>" tR="</$tag>"
xml=$(< yourxmlfile)
while case $xml in *"$tL"* ) :;; * ) break;; esac; do
  t1=${xml#*"$tL"} t2=${t1%%"$tR"*} xml=${t1#*"$tR"}
  echo "${tL}${t2}${tR}"
done

真珠

perl -lne "print for/<$tag>.*?<\/$tag>/g" yourxmlfile

sed -e "
  s|<$tag>|\n&|
  s/.*\n//
  s|</$tag>|&\n|
  /\n/P;D
" yourxmlfile

出力

 <data>asdf</data>
 <data>asdf</data>
 <data>asdf</data>
 <data>asdf</data>

答え4

前提は、XMLに改行文字がないことです。 XMLを標準形式にするには、><の間に\ nを挿入してみてはいかがでしょうか?

例: - 与えられたxmlを使用してstackというファイルを作成しました。

以下は改行文字を導入する sed 操作です。

 cat stack|sed -e 's/></>\n</g'

<ID>2</ID>
<data>asdf</data>
<data2>asdf</data2>
<dataX>asdf</dataX>
<dateAccessed>somedate</dateAccessed>

これで目的のタグにアクセスできます。

関連情報