web-dev-qa-db-ja.com

sed:見つかった場合に行を置き換える方法、または見つからなかった場合にファイルの最後に追加する方法

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

私の現在の方法は、最初のパスでそれを削除し、次に2番目のパスでファイルの最後に追加することで機能しますが、このメソッドは行の順序を混乱させます(これも2つの異なるコマンドです)。

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

とにかくこれを行うには、つまり単一のsed行で行の順序を維持しますか?他のユーティリティ(awk、...)がこれを行う場合、私はそれをsedに引き継ぎます。

37
BlakBat

sedを使用すると、実際には非常に簡単です。行が一致する場合は、holdスペースにコピーするだけで、substituteの値になります。
la$t行e xchangeのホールドスペースとパターンスペースで、後者が空かどうかを確認します。空でない場合は、置換が既に行われているため、何もする必要はありません。空の場合は一致が見つからなかったことを意味するため、パターンスペースを目的のvariable = valueで置き換えてから、ホールドバッファーの現在の行に追加します。最後に、再びe xchange:

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
31
don_crissti

これはおそらく短縮できます。これは単一のsedコマンドではなく、grepも使用しますが、これは基本的に必要なもののようです。これは1行で、ファイルをその場で編集します(一時ファイルは編集しません)。

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

sedhold spaceは扱いが簡単ではないので、これはより単純なsedアプローチです。 hold spaceに慣れている場合は、don_crisstiアプローチを使用すると、既存のラインから何でも保存できるようになりますが、これは通常非常にまれです。

このアプローチでは、ドロップする行を除いてすべてを印刷し、最後に置換を追加します。

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

他の回答に基づいて、変数がファイルに存在する場合に変数の値を置き換え、存在しない場合はファイルの末尾に追加します(投稿された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

grepechoを使用して、空のレコードを作成します。

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

各行はエラーコード0でエスケープします。

1
MUY Belgium

「インプレース編集」は自動ではありませんが、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

実際には次のもので動作します:sed -i '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile選択した回答に-iがありません。

0
Yogesh Kamat