
次のXMLファイルがあります(A.xml
)。
<?xml version="1.0"?>
<RunParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RunParametersVersion>NextSeq_4_0_0</RunParametersVersion>
<ReagentKitSerialWasEnteredInBaseSpace>false</ReagentKitSerialWasEnteredInBaseSpace>
<ExperimentName>210913-RUN61-COCO</ExperimentName>
<PurgeConsumables>false</PurgeConsumables>
<MaxCyclesSupportedByReagentKit>92</MaxCyclesSupportedByReagentKit>
<ModuleName />
<ModuleVersion />
</RunParameters>
RUN61
XMLタグポートを含むbash変数を設定したいと思います<ExperimentName>210913-RUN61-COCO</ExperimentName>
。タグ値は常に次のような構造を持ちます。
重要ではない -関連-関係ない
ダッシュで区切ってください。
grep
私は良い結果なしで試しました。
runNumber=$(grep -o '<ExperimentName>.*</ExperimentName>' | cut -d '-' -f2 A.xml)
何をすべきか知っていますか?
答え1
構造化データを扱うため、専用パーサーを使用する必要があります。たとえば、次のxmlstarlet
タグ値を抽出する必要がありますcut
。
xmlstarlet sel -t -c "string(/RunParameters/ExperimentName)" A.xml | cut -d- -f 2
だから、あなたは使用することができます
runNumber=$(xmlstarlet sel -t -c "string(/RunParameters/ExperimentName)" A.xml | cut -d- -f 2)
答え2
以下のみを使用してくださいxmlstarlet
。
experiment_name=$(
xmlstarlet sel -t \
-m '/RunParameters/ExperimentName' \
-v 'substring-before(substring-after(., "-"), "-")' file.xml
)
これは、関心のあるノードと一致し、2つの関数を使用してsubstring-after()
そのノード値の中間部分を削除しますsubsring-before()
。
次に、xmlstarlet
出力を変数に割り当てますexperiment_name
。
または以下xq
で使用してください。https://kislyuk.github.io/yq/
experiment_name=$(
xq -r '.RunParameters.ExperimentName | split("-")[1]' file.xml
)
これはノードの値をダッシュに分割し、結果の配列の2番目の要素を返します。
答え3
Raku(以前のPerl_6)の使用
raku -MXML -e 'for open-xml($*ARGFILES) {.elements(:TAG<ExperimentName>)>>.contents.put};' < input.xml
入力例:
<?xml version="1.0"?>
<RunParameters xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RunParametersVersion>NextSeq_4_0_0</RunParametersVersion>
<ReagentKitSerialWasEnteredInBaseSpace>false</ReagentKitSerialWasEnteredInBaseSpace>
<ExperimentName>210913-RUN61-COCO</ExperimentName>
<PurgeConsumables>false</PurgeConsumables>
<MaxCyclesSupportedByReagentKit>92</MaxCyclesSupportedByReagentKit>
<ModuleName />
<ModuleVersion />
</RunParameters>
出力例:
210913-RUN61-COCO
他の人が述べたように、このタスクには専用のXMLパーサーを使用することをお勧めします。簡単に言えば、上記のコードでは、Rakuはbashコマンドラインから呼び出され、そのコマンドを使用して-M
モジュールをロードします。上記のコードはシェルリダイレクトに依存しています(リダイレクトなしで入力を文字列化する必要があります)。 XMLファイルを使用して必要なコンテンツを開き、照会、抽出、および返すために使用します。XML
-MXML
<
open-xml()
$*ARGFILES.Str
open-xml
TAG
contents
put
実際、OPは出力部分をcut
抽出するための非常に良いコードを提供し、上記のRakuソリューションはOPのコードを通して簡単にパイプすることができます。ただし、Rakuソリューション全体の場合は、RUN61
上記のRakuコードに.split("-")[1]
呼び出し.contains
を挿入するだけです。.put
raku -MXML -e 'for open-xml($*ARGFILES.Str) {.elements(:TAG<ExperimentName>)>>.contents.split("-")[1].put};'
https://github.com/raku-community-modules/XML
https://www.raku.org
答え4
次のように名前を抽出することもできますgrep
(オプションで-E
拡張正規表現を許可)。
runNumber=$(grep -Eo '[[:alnum:]]+-[[:alnum:]]+' A.xml | cut -d- -f2)
そのラベルの行を確認するには、grep
別のコマンドで事前フィルタリングできます。
runNumber=$(
grep '<ExperimentName>' A.xml \
| grep -Eo '[[:alnum:]]+-[[:alnum:]]+' \
| cut -d- -f2
)
メモ:
XPath式に基づくソリューション:
- 読みやすさ
- フォールトトレランスが高い場合があります
- しかし、いくつかの追加の依存関係を導入できます。