bashを使用してファイル内の各行の文字列を見つけ、同じ行の別の文字列に置き換えます。

bashを使用してファイル内の各行の文字列を見つけ、同じ行の別の文字列に置き換えます。

これは私のスクリプトです。

#! /bin/bash

# C-band Edit
dqt='"'
str5="polarization=${dqt}2${dqt}"
for x in {3600..4200} do;
    sed -i "/$str5.*$x/s/$x/$((x-600))/" satellites.xml
done

私が望むのは、str5を含むSatellites.xmlのすべての行で、3600から4200の間の数値xをx-600に置き換えることです。しかし、上記のスクリプトで構文エラーが発生します。

ベストアンサー1

x-600ちょうどあなたがリテラル文字列を意味するのではなく、「3600と4200の間のすべての値から600を引く」という意味だと思いました。この場合、sedではなくPerlを使用してください。

echo "$str5. foo bar 3200 3964 4155 4200 4255" |
  perl -p -e "if (/$str5/) {s/3[6789]\d\d|4[01]\d\d|4200/$&-600/eg}"
polarization="2". foo bar 3200 3364 3555 3600 4255

これはPerlの/e正規表現修飾子を使って右($&-600)を次のようにします。Perl式で評価されます。$&は一致する値を含むPerl変数なので、$&-600値から600を引くことを意味します。

これが本当に欲しいものなら、以下に元の答えを残しておきます。また、上記のPerlの回答とまだある程度関連する有用な説明があるからです。

sedと同様に、Perlには-i内部編集オプションがあるため、Satellites.xmlファイルに直接適用できます。man perlrun詳細より。

perl -i -p -e "if (/$str5/) {s/3[6789]\d\d|4[01]\d\d|4200/$&-600/eg}" satellites.xml

また、注目すべき点は、XMLファイルで作業するときにおそらくXMLパーサーを使用する必要があることです。幸いなことに、Perlにはいくつかのオプションがあります。XML::パーサーまたはコレクションlibxml-perl


実際の入力サンプルがないので、変更されたものと変更されていないことを示す例を作成しました。

str5='polarization="2"'

echo "$str5. foo bar 3500 3964 4155 4200 4255" | 
  sed -e "/$str5/ {s/3[6-9][0-9][0-9]/3-600/g; s/4[01][0-9][0-9]/4-600/g; s/4200/4-600/g}"
polarization="2". foo bar 3500 3-600 4-600 4-600 4255

英語におおよそ翻訳すると、「現在の行に$ str5()が含まれている場合は、polarization="2"これらの3つの操作をその行に適用してください」。s///

メモ:

  • 3600..4200でループする必要はありません。これにより、すべての内容が変更されます。一つsed600回実行の代わりに実行されます。

  • 3600~4200の値を変更したい。つまり、3つの検索と置換操作が必要です。

    • ワンピース 3600-3999
    • 4000-4199ワンピース
    • 1セットで4200ウォンです。
  • または、s///最後の2つのタスクを1つにまとめて2つのタスクとして実行できます。

      sed -e "/$str5/ { s/3[6-9][0-9][0-9]/3-600/g; s/4[01][0-9][0-9]\|4200/4-600/g }"
    
  • 正規表現を最適化する他の方法もたくさんありますが、それを行うほど、後で読んで修正するのは難しくなります。

  • 39644155および4200変更されました。 3500しかし、そうでは4255ありません。必要以上に

  • [0-9]期待どおりに動作しません一部ロケール(範囲に異なる文字があります)具体的には、どのロケールが何であるかはわかりませんが、[0-9]完全に依存しないほど頻繁に言及されていることを見てください。これが影響する場合は、[[:digit:]]代わりに使用する[0-9]か、perl -p代わりに使用できます(代わりにsed使用できます)。 rangeにも同様に適用されます。代わりに使用してください。\d[0-9][6-9][6789]

  • $str5最後に、変数に何を入れるかは非常に注意する必要があります。sedコマンドに挿入されるので、sedスクリプトを簡単に破ることができます(たとえば、$str5aを含めると一致が/壊れます)。/$str5/sedは、スクリプト部分がシェル変数から来ていることを知らず、実行するように指定されたスクリプトのみを表示します。

    また、文字列全体は次のようになります。sedによって正規表現として解釈される\- これは、正規表現メタ文字がそう.でなければリテラル文字として解釈されないことを意味します。\.

おすすめ記事