linux – sed:見つかった場合に行を置換したり、見つからなかった場合にファイルの最後に追加したりするにはどうすればいいですか?

awk command-line linux sed

コメント(#で始まる)とVARIABLE=値の行だけを含む単一の入力ファイルで、見つかった場合には単一の変数の値を置き換え、見つからなかった場合にはペアをファイルの最後に追加することは可能でしょうか?

私の現在の方法は、1パス目で削除して2パス目でファイルの最後に追加するという方法で動作しますが、この方法だと行順がぐちゃぐちゃになってしまいます(しかも2種類のコマンドになっています)

sed -r "/^FOOBAR=.*$/d"      -i samefile &&
sed -r "$ a\FOOBAR=newvalue" -i samefile

これを行う方法はないのでしょうか?もし他のユーティリティ (awk, ….) がこれを行うならば、私は sed よりもそれを利用したいと思います

  39  None  2013-05-02


ベストアンサー

sedでは、実際には非常に簡単です: 一致する行があれば、それをh古いスペースにコピーし、s値を置換します。 la$t行のexホールドスペースとパターンスペースを変更し、後者が空かどうかをチェックします。もし空でなければ、すでに置換が行われているので何もしなくてもよいことを意味します。もし空であれば、それはマッチするものが見つからなかったことを意味するので、パターンスペースを希望の変数=値に置き換えて、ホールドバッファの現在の行に追加します。最後に、exを再度変更します

sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile

上記はgnu sedの構文です。ポータブルです

sed '/^FOOBAR=/{
h
s/=.*/=newvalue/
}
${
x
/^$/{
s//FOOBAR=newvalue/
H
}
x
}' infile

34  don_crissti  2015-09-22


これはたぶん短縮できると思います。単発のsedコマンドではなく、grepも使っていますが、基本的にはこれでいいようです。単行で、その場で編集してくれます(テンポラリファイルはありません)

grep -q "^FOOBAR=" file && sed "s/^FOOBAR=.*/FOOBAR=newvalue/" -i file ||
sed "$ a\FOOBAR=newvalue" -i file

18  snapshoe  2013-05-02


sed sed hold space を扱うのは簡単ではないと思うので、ここではよりシンプルな sed のアプローチを紹介します。hold space に慣れているのであれば、don_crissti のアプローチを使うことで、既存の行から何かを保存する機会を増やすことができますが、通常、これは非常にまれです

この方法では、落としたい行以外をすべて印刷して、最後に置き換えを追加します

sed -n -e '/^FOOBAR=/!p' -e '$aFOOBAR=newvalue' infile

16  haridsv  2016-11-16


他の回答に基づいて、変数がファイルに存在する場合は変数の値を置換し、存在しない場合はファイルの最後に追加します(投稿されているsedコマンドが行うこととは異なります)

perl -ne '$c=1 if s/^FOOBAR=.*$/FOOBAR=newvalue/;
print;
END{print "FOBAR=newvalue" unless $c==1}' file > tmpfile &&
mv tmpfile file

3  terdon  2013-05-02


場内編集」は自動ではありませんが、awkでは少し楽になりました

awk -v varname="FOOBAR" -v newval="newvalue" '
BEGIN {FS = OFS = "="}
$1 == varname {$2 = newval; found = 1}
{print}
END {if (! found) {print varname, newval}}
' file > tempfile &&
mv tempfile file

1  glenn jackman  2013-05-02


空のレコードを作成するには、grepechoを使用するだけです

grep -q '^FOOBAR=' somefile || echo 'FOOBAR=VALUE' >> somefile
sed -i 's/FOOBAR=.*$/FOOBAR=VALUE/' somefile

各行はエラーコードゼロでエスケープされます

1  MUY Belgium  2016-03-08


実際には以下のように動作します。 sed -i '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile 選択された答えの中に-iがありません

0  Yogesh Kamat  2016-04-22


を使ってPerlでこれを行い、インプレースではこれで問題なく動作するようになりました

grep ^FOOBAR= my.file && perl -i -ple "s/^FOOBAR=.+/FOOBAR=newvalue/g" my.file || echo FOOBAR=newvalue >> my.file

-1  antweiss  2015-10-29


タイトルとURLをコピーしました