.txtファイルからlast_nameを印刷する方法は?

.txtファイルからlast_nameを印刷する方法は?

私のLinuxコンピュータには次のファイルがあります。

<names>
<first_name>Mohammed Sani</first_name>
<last_name>ABACHA</last_name>
<aliases>
<alias>ABACHE,Mohammed Sani</alias>
<alias>SANI,Mohammed</alias>
</aliases>
<low_quality_aliases>
<alias xsi:nil="true"/>
</low_quality_aliases>
<alternative_spelling xsi:nil="true"/>
</names>

次のコマンドを使用して名前を印刷しますが、名前のみを印刷します。

sed -n 's:.*<first_name>\(.*\)</first_name>.*:\1:p' 'test.xml' > name.txt

姓を追加するにはどうすればよいですか?

答え1

名前と姓データが同じ行にあり、その間にタブがあることを望んでいるとします。

使用xmlstarlet:

xmlstarlet sel -t -m '/names' \
    -v 'first_name' -nl \
    -v 'last_name' -nl file.xml 2>/dev/null |
paste - -

このコマンドは、そのノードとその下のノードの値を解析し、それぞれxmlstarlet1行ずつ出力します。first_namelast_namenames

タブ文字を区切り文字として使用して、出力の2行を1行に貼り付けますpaste。たとえば、withを使用する-d ','paste、カンマ区切りの出力を取得できます。

/dev/null後でドキュメントにxmlstarlet正しいいくつかの偽の名前空間宣言があるため、標準エラーストリームにリダイレクトします。


xq以下で使用https://kislyuk.github.io/yq/:

xq -r '.names | [ .first_name, .last_name ] | @tsv' file.xml

これは@tsv演算子を使用してタブ区切りの出力を生成します。上記のコードと同じデータを出力しますxmlstarletが、XPath式の代わりに式を使用しますjq

代わりに、完全に引用されたCSV出力を@tsv取得してください。@csv

答え2

2番目のコマンドを追加できますs

sed -n 's:.*<first_name>\(.*\)</first_name>.*:\1:p;s:.*<last_name>\(.*\)</last_name>.*:\1:p' 'test.xml' > name.txt

または拡張正規表現を使用してください。

sed -En 's:.*<(first|last)_name>(.*)</\1_name>.*:\2:p' 'test.xml' > name.txt

更新:両方の名前を同じ行に出力するように要求

同じ行に出力を配置するには、別のスクリプトを介して空白の行にパイプするだけです。

sed -En 's:.*<(first|last)_name>(.*)</\1_name>.*:\2:p' test.xml | sed 'H;1h;$!d;g;s/\n/ /g' > name.txt

パターン空間のすべての行を連結するために使用されますH,1h;$1d;gHすべての行を予約済みスペースに追加し、1h前の改行を防ぐために最初の行の予約済みスペースを上書きし、最後の行を除くすべての$!d行の処理を停止し、 、g予約された空間内容をパターン空間に移動)。次に、s/\n/ /gすべての改行を空白に置き換えます。あなたの場合は、g常に2行しかないと確信している場合はそれを削除できます。

LinuxではGNUがあり、同じ結果がsed得られます。sed -z 's/\n/ /g'

よりエレガントに、ファイルで複数の名前のペアを処理できる場合は、次のこともできます。

sed -e '/.*<first_name>\(.*\)<\/first_name>.*/{s//\1/;h;}' -e '/.*<last_name>\(.*\)<\/last_name>.*/!d;s//\1/;H;g;s/\n/ /' 'test.xml' > name.txt

関連情報