web-dev-qa-db-ja.com

まだ存在しない場合にのみファイルに行を追加する

構成ファイルの最後に次の行を追加する必要があります。

include "/configs/projectname.conf"

lighttpd.confというファイルに

これを行うためにsedを使用することを検討していますが、どうすればよいかわかりません。

行がまだ存在しない場合にのみ挿入するにはどうすればよいですか?

125
Benjamin Dell

単純にしてください:)

grep+echoで十分です:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar

編集:@cerinおよび@ thijs-woutersの提案を組み込みました

230
drAlberT

これは、grepechoを使用して、ファイルが存在しない場合にのみファイルに行を追加する、クリーンで読みやすく再利用可能なソリューションです。

LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
66
rubo77

sedバージョンは次のとおりです。

sed -e '\|include "/configs/projectname.conf"|h; ${x;s/incl//;{g;t};a\' -e 'include "/configs/projectname.conf"' -e '}' file

文字列が変数内にある場合:

string='include "/configs/projectname.conf"'
sed -e "\|$string|h; \${x;s|$string||;{g;t};a\\" -e "$string" -e "}" file
12

保護されたファイルに書き込む場合、@ drAlberTと@ rubo77の回答は、Sudo >>を実行できないため、役に立たない可能性があります。 同様に単純な解決策 、それから、tee --appendを使用することになります:

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE"  || echo "$LINE" | Sudo tee --append "$FILE"
7
hamx0r

ある日、誰かがこのコードを「レガシーコード」として扱うためにhaveをした場合、そのような人は、以下のような、より難解なコードを書くと感謝するでしょう。

grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
  echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi
6
Marcelo Ventura

別のsedソリューションは、常に最後の行に追加し、既存のものを削除することです。

sed -e '$a\' -e '<your-entry>' -e "/<your-entry-properly-escaped>/d"

「適切にエスケープ」とは、エントリに一致する正規表現を配置すること、つまり、実際のエントリからすべての正規表現制御をエスケープすること、つまり^ $/*?+()の前にバックスラッシュを配置することを意味します。

これはファイルの最後の行で失敗する可能性があります。または、絡まる改行がない場合はわかりませんが、それはいくつかの気の利いた分岐で対処することができます...

5
Robin479

awkを使用する

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file
3
ghostdog74

Grepを使用した答えは間違っています。行全体に一致するように-xオプションを追加する必要があります。一致しない場合、#text to addのような行は、text to addを正確に追加するときに一致します。

したがって、正しい解決策は次のようなものです。

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
1
Thijs Wouters

sed:を使用行末に挿入します。もちろん、通常どおり変数を渡すこともできます。

grep -qxF "port=9033" $light.conf
if [ $? -ne 0 ]; then
  sed -i "$ a port=9033" $light.conf
else
    echo "port=9033 already added"
fi

oneliner sedを使用

grep -qxF "port=9033" $lightconf || sed -i "$ a port=9033" $lightconf

echoを使用はルートでは機能しない場合がありますが、このように機能します。ただし、パスワードを要求する可能性があるため、実行しようとしている場合は自動化できません。

特定のユーザーのルートから編集しようとしたときに問題が発生しました。前に$usernameを追加するだけで修正されました。

grep -qxF "port=9033" light.conf
if [ $? -ne 0 ]; then
  Sudo -u $user_name echo "port=9033" >> light.conf
else
    echo "already there"    
fi
1
Rakib Fiha

書き込み権限が制限されているファイルを編集する必要があったため、Sudoが必要でした。 ghostdog74の回答から作業し、一時ファイルを使用します。

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file > /tmp/file
Sudo mv /tmp/file file
0
webdevguy