sed を使用して xml タグの 1 文字を別の文字に置き換えます。

sed を使用して xml タグの 1 文字を別の文字に置き換えます。

S文字を次に置き換える必要がありますT

<episode-num system="onscreen">S1 E12</episode-num>

私の予想結果:

<episode-num system="onscreen">T1 E12</episode-num>

Gitがどのように深く機能するのかわかりませんが、XMLタグの対応する文字を変更するために使用し、フォーラムで調査した結果、いくつかの情報を見つけて次のコマンドラインを試しました。

sed -e :l -e 's@\(<episode-num system="onscreen">.*\)S\([^amp;]\)\(.*</episode-num>\)@\1T\2\3@;tl' guide.xml

しかし、うまくいきません。助けてください。

答え1

次のXML文書があるとしましょう。

<data>
<episode-num system="onscreen">S1 E12</episode-num>
<episode-num system="onscreen">S1 S12</episode-num>
<episode-num system="onscreen">T1 S12</episode-num>
</data>

S...ノード値のすべての文字を置き換えようとしています。Tepisode-numから始まるS

xmlstarlet次のことができます。

xmlstarlet ed -u '//episode-num[starts-with(text(),"S")]' \
    -x 'translate(text(),"S","T")' file.xml

episode-num文書内の場所に関係なく、すべてのノードを変更できます。ただ修正したい場合特別なノードをクリックし、//episode-numXPath式をより正確なパスに変更します。

上記のサンプル文書では、上記のxmlstarletコマンドは次のように生成します。

<?xml version="1.0"?>
<data>
  <episode-num system="onscreen">T1 E12</episode-num>
  <episode-num system="onscreen">T1 T12</episode-num>
  <episode-num system="onscreen">T1 S12</episode-num>
</data>

xq(からhttps://kislyuk.github.io/yq/)のようなxmlstarlet上記と:

xq -x '(.data."episode-num"[] | select (."#text"|startswith("S")))."#text" |= gsub("S";"T")' file.xml

これは、入力文書がサンプル文書と同じ構造を有すると仮定する。 XMLパーサーを使用して文書を解析し、内部的にJSONに変換します。生成されたJSONドキュメントを呼び出してjq与えられた式を適用し、最後にすべてをXMLに変換します。

私が使用しているサンプル文書の場合、式が実際に適用される内部JSON文書はjq次のとおりです。

{
  "data": {
    "episode-num": [
      {
        "@system": "onscreen",
        "#text": "S1 E12"
      },
      {
        "@system": "onscreen",
        "#text": "S1 S12"
      },
      {
        "@system": "onscreen",
        "#text": "T1 S12"
      }
    ]
  }
}

答え2

行に別の文字列が含まれている場合にのみ、特定の文字列を置き換えます。sed

文字列を含む行だけを置き換えます。free

sed '/free/s/i/I/g' example.txt
  • '/free/s/i/I/g'
    • /free/- この文字列が含まれている場合にのみ行を置き換えます。
    • s- sedの代替コマンド
    • /i/- 一致させる正規表現は何ですか?
    • /I/- 一致する部分文字列を置き換える
    • /g- ラインのすべての試合に対して交換を繰り返す交換フラグ

仮説に対する解決策

あなたのテスト文字列は<episode-num system="onscreen">

次の内容を含むファイルがあるとします。

$ cat test.xml 
<data>
<episode-num system="onscreen">S1 E11</episode-num>
<episode-num system="onscreen">S1 E12</episode-num>
<episode-num system="onscreen">T1 E13</episode-num>
<some data>S1 E1</episode-num>
</data>

あなたのsedソリューションは次のとおりです

$ sed '/<episode-num system="onscreen">/s/S/T/g' test.xml 
<data>
<episode-num system="onscreen">T1 E11</episode-num>
<episode-num system="onscreen">T1 E12</episode-num>
<episode-num system="onscreen">T1 E13</episode-num>
<some data>S1 E1</episode-num>
</data>

このソリューションのソースはここ

答え3

Perl one-lignerは良いアプローチではありません。それでも:

perl -MXML::DT -e 'print dt("ex1.xml", "episode-num" => sub{$c=~ s/S/T/; toxml})'

どこ:

  • -XML::DT = XML :: DTモジュールをインポートして使用します(この場合はdt関数
  • dt( file, processor)=提供されたプロセッサを使用してファイルを下に翻訳する
  • episode-num => sub{...}=subすべての要素に適用episode-sum
  • $c = s/S/T/ ; toxml=要素コンテンツのSをT(= $ c)に置き換えて、episodeXML要素を再計算します。

(必要ならsudo cpanm XML::DT

関連情報