私はsudoers、sysctl.confなどに行を追加するために多くの一時スクリプトを書いています。通常、私はlineinfile ansibleモジュールを使用します。しかし、時にはこれを行うことができないので、次を使用します。
WHAT_I_WANT='my line of text = something'
WHAT_TO_REPLACE='my line of text = .*'
FILE_TO_EDIT=conf_file.conf
if ( ! grep -q "^$WHAT_I_WANT\$" FILE_TO_EDIT ); then
echo "$WHAT_I_WANT" >> FILE_TO_EDIT
else
sed -i "s/$WHAT_TO_REPLACE/$WHAT_I_WANT/g' FILE_TO_EDIT
fi
私の考えには、これを行うより効率的な方法があるようです。理想的には、1行と1言語を使用することをお勧めします(正規表現の一致、コメント化された行の削除、およびファイルのバックアップを許可する方法で)。しかし、それが何であるかはわかりません。
答え1
- 私の考えでは、長い文字列を置き換えるために非常に長い変数名を使用するのは非生産的です。
- grep/sed コマンドで変数を拡張するには、二重引用符を使用します。
.*
変数の割り当てにワイルドカード文字を使用すると、ファイル名拡張子の実行(ワイルドカード)- 次のスクリプトは、ifの代わりに
&&
成功または失敗時に条件付き実行を使用します。||
REPL='something'
PATT='my line of text = '
FILE=conf_file.conf
cat $FILE
echo '========='
grep -q "^$PATT" $FILE && (sed -i "s/^$PATT.*$/$PATT$REPL/" $FILE) || (echo "$PATT$REPL" >> $FILE)
cat $FILE
答え2
実際には単純な文ではありませんが、1回の呼び出しでこれを実行できますsed
。
sed -e '
/pat/{s//repl/g;h;}
$!b
G
s/\n..*//;t
s/$/repl/
' yourfile
注:私はあなたのようにシェル変数を使用するのではなく、パターンと置換をそれぞれ表すために意図的にpat
とを使用しました。repl
基本的に、sedコードの流れを妨げる主な理由は2つあります。 +正確さのために両方を参照し、異なる動作をする必要があります。その仕事はあなたに任せます。
フロー:たとえば、ファイルに/ pat /が含まれていない場合は、$ ! bコマンドによってすべての行が標準出力にインポートされ、Gとして追加されると、最後の行は空の予約のみを確認するため、インポートされず、追加がt
あります。仕事 。
/pat/ 行が表示された場合は s///-ed で、予約された領域が表示されます。最後の行でなければ標準出力に進みます。 eofの場合はホールドを確認し、nullではないため(仮定repl
)、NONEMPTY
パターン空間からホールドが削除された後にテストパスを選択します。
Perl
コードの逐語的意図と一致する明確性を提供します。
perl -lne '$a += s/pat/repl/g,print}{print q[repl] unless $a'
解釈:この変数は$a
置換回数のカウンタとして使用されます。最後に、以前に置き換えが行われていない場合は、ファイルに追加します。
変数を介してパターン/交換情報を提供する場合は、次のようにできます。
WHAT_I_WANT='my line of text = something'
WHAT_TO_REPLACE='my line of text = .*'
FILE_TO_EDIT=conf_file.conf
perl -li -sn -e '
$a += s/$pat/$repl/g,print}{print $repl unless $a
' -- -pat="$WHAT_I_WANT" -repl="$WHAT_TO_REPLACE" -- "$FILE_TO_EDIT"