たとえば、次はファイルの内容です。
$ 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
なく、単純な文字列比較を実行する機能もありません(正規表現の一致とは対照的に)。変数に 。awk
ENVIRON
sed
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