説明する

説明する

たとえば、次はファイルの内容です。

$ cat file
Name=Tom
Value=10
Name=Tom
Name=Harry
Value=20

名前の後に値が表示されない場合があります。したがって、私がする必要があるのは、Name = Tomパターンを見つけて値を変更することです。ただし、名前の直後に表示される場合にのみ該当します。どうすればいいですか?

答え1

そしてawk

awk 'prev ~ /^Name=(Tom|Anything)$/ && /^Value=/ {$0 = "Value=123"}
     {print; prev = $0}'

または 名前そして新しい変数に保存:

export NAME=Tom VALUE=123
awk 'prev == "Name=" ENVIRON["NAME"] && /^Value=/ {
       $0 = "Value=" ENVIRON["VALUE"]
     }
     {print; prev = $0}'

の場合、sedその内容は次のとおりです。

sed -e 'x;/^Name=Tom$/{g;/^Value/s/=.*/=123/;h;b' -e '}' -e g

いつものようにawk。また、変数に格納されている任意の値を処理するために'sと同じ機能もsedなく、単純な文字列比較を実行する機能もありません(正規表現の一致とは対照的に)。変数に 。awkENVIRONsed

sed -e "x;/^Name=$NAME\$/{g;/^Value/s/=.*/=$VALUE/;h;b" -e '}' -e g

が厳密に制御されていないと、コマンドインジェクションの脆弱性になります(少なくともGNUの場合sed)。$NAME$VALUE

答え2

よりコンパクトで簡単になりました。

sed 'G;/^Value=/s/=.*\nName=Tom/=42/;s/\n.*//;h' file

これにより、予約済みスペースの前の行が各行に追加されます。行の場合、値が予約済みスペースにある場合、Value=値は置き換えられます。Name=Tomそれ以外の場合は、追加された行が削除され、その行は次のサイクルのために予約されたスペースに保存されます。

答え3

sed -e '
   /^Name=Tom$/!b
   $!N
   /\(\nValue\)=.*/s//\1=NEW_VALUE/
   P;D
' data.inp

説明する

  • Tomという名前の行を探します。不一致は標準出力に渡されます。
  • その後、最後の行でない場合は、パターン空間に次の行を追加しようとします。
  • 追加した行で正規表現 Value= を探し、その場合は値が NEW_VALUE に変更されます (必要に応じて変更する必要があります)。
  • P;D => は、Name=Tom の直前に減らされた\n の左側にパターン空間部分を印刷し、その部分を削除します。 Value = NEW_VALUEが残ったので、sedスクリプト行の先頭に移動します。 /^Name=Tom$/!b 明らかに、この操作は失敗するため、標準出力に移動されます。これは、連続したName = Tom行を処理するために行われます。

結果

Name=Tom
Value=NEW_VALUE
Name=Tom
Name=Harry
Value=20

関連情報