回答:
シンプルにしてください:)
grep + echoで十分です:
grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
-q
静かにして-x
行全体に一致-F
パターンはプレーンな文字列です編集:@cerinおよび@ thijs-woutersの提案を組み込みました。
grep -vq ...
echo
てcat
複数行のヒアドキュメントを構成ファイルにトリガーします。
-s
だけでその行で新しいファイルを作成し、ファイルが存在しない場合にエラーを無視します。
これは使用して、きれいな読み取りおよび再利用可能な解決策になるgrep
とecho
、それはまだ存在しない場合にのみファイルに行を追加します:
LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
ライン全体を一致させる必要がある場合 grep -xqF
追加-s
だけでその行で新しいファイルを作成し、ファイルが存在しない場合にエラーを無視します。
sudo grep -qF "$LINE" "$FILE" || echo "$LINE" | sudo tee -a "$FILE"
-
。
--
grepコマンドに追加したので、ダッシュで始まる$ LINEがオプションとして解釈されなくなりました。
ここに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
sed -i -e '\|session.*pam_mkhomedir.so|h; ${x;s/mkhomedir//;{g;tF};a\' -e 'session\trequired\tpam_mkhomedir.so umask=0022' -e '};:F;s/.*mkhomedir.*/session\trequired\tpam_mkhomedir.so umask=0022/g;' /etc/pam.d/common-session
sed
何年も使用してきましたが、ほとんどがs
コマンドだけです。hold
そしてpattern
スペーススワップは私を超えています。
1日は、他の誰かが、場合持っている「レガシーコード」として、このコードに対処するために、あなたのような、あまり平凡なコードを書く場合、その人は感謝するだろうということ
grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi
別のsedソリューションは、常に最後の行に追加し、既存のものを削除することです。
sed -e '$a\' -e '<your-entry>' -e "/<your-entry-properly-escaped>/d"
「適切にエスケープする」とは、エントリに一致する正規表現を配置すること、つまり実際のエントリからすべての正規表現コントロールをエスケープすること、つまり^ $ / *?+()の前にバックスラッシュを配置することを意味します。
これはあなたのファイルの最後の行で失敗するかもしれません、またはぶら下がっている改行がない場合、私にはわかりませんが、それはいくつかの気の利いた分岐で対処できます...
sed -i.bak -e '$a\' -e "$NEW_IP\t\t$HOST.domain\t$HOST" -e "/.*$HOST/d" /etc/hosts
sed -i -e '/<entry>/d; $a <entry>'
d
コマンドはsedプログラムを再起動して、a
ペンドをスキップするためです。
a
ペンドはd
eleteの前に実行する必要があります:sed -i -e '$a<entry>' -e '/<entry>/d'
。元の答えとほぼ同じです。
awkを使用する
awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file
file file
は、同じファイルに対して2つのパスを作成するためです。NR==FNR
最初のパスではtrueですが、2番目のパスではありません。これは一般的なAwkイディオムです。
grepを使用した答えは間違っています。行全体を一致させるには-xオプションを追加する必要があります。そうしない#text to add
と、正確に追加しようとすると、行が一致しtext to add
ます。
したがって、正しい解決策は次のようなものです。
grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
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
ワンライナーsedの使用
grep -qxF "port=9033" $lightconf || sed -i "$ a port=9033" $lightconf
エコーの使用はルートの下では機能しないかもしれませんが、このように機能します。ただし、パスワードを要求する可能性があるため、自動化しようとしている場合は自動化できません。
特定のユーザーのルートから編集しようとしたときに問題が発生しました。$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
書き込み権限が制限されているファイルを編集する必要があったため、必要に応じて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
crudini
が適切なオプションである可能性があります(ただしlighthttpdにはまだ対応していません)