文字列の存在に応じたファイルの編集

文字列の存在に応じたファイルの編集

file1たとえば、次のような入力ファイルがあります。

WRITE=2
START=1
SMEAR=0
MIN=6
MAX=100

私の問題は文字列を検索し、SMEAR文字列が存在する場合は行全体をSMEAR=-5。ただしSMEAR、存在しない場合は新しい行を挿入する必要がありますSMEAR=-5。最終的にこの行はSMEAR=-5一度だけ現れなければなりません。 sed を使用して文字列を置き換えることができます。

 sed -i '/SMEAR/c\SMEAR=-5' file1

あるいは、文字列を新しい行に挿入することもできます。

 sed -i '10i SMEAR=-5' file1

しかし、ファイルに存在する文字列に基づいて文字列をどのように結合できますか?

編集する:SMEAR値を変数として渡すことができれば役立ちます。

答え1

ユースケースでは、行の順序は重要ではないようです。これを考えると、ex単に以下を使用します。

  1. SMEAR次のすべてのインスタンスを削除します。
  2. 目的の行を挿入してください。

次のことができます。

printf '%s\n' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt

最初のコマンドは、正規表現に一致するすべての行をg完全に削除します。d/SMEAR/

次のコマンドは、a最後の行()の$後に行を追加することですSMEAR=-5。追加するテキストの終わりです.

このxコマンドは変更を保存して終了します。

各コマンドは改行文字で終わり、printf '%s\n'それを使用してに送信しますex


また見てくださいこの非常に類似したソリューションこれは私がしばらく前にvi / Vim Stack Exchangeに書いたものです。


変更を保存せずに変更されたファイルをコマンドラインに印刷して変更をテストするには、次の2つのxコマンドを置き換えます。%p 'q!'

printf '%s\n' 'g/SMEAR/d' '$a' 'SMEAR=-5' . %p 'q!' | ex file.txt

%「フルバッファ」を意味し、これがp印刷されます。

q!「やめる、変化をあきらめる」という意味だ。

変更を次に保存します。新しい%pファイルを次のように置き換えますw newfile.txt

printf '%s\n' 'g/SMEAR/d' '$a' 'SMEAR=-5' . 'w newfile.txt' 'q!' | ex file.txt

これにより、w変更されたバッファが作成されますnewfile.txt

または、次のように最初からこれを実行してバックアップを作成し、変更したファイルの内容を元の場所に保存することもできますfile.txt

printf '%s\n' 'w file.txt.bak' 'g/SMEAR/d' '$a' 'SMEAR=-5' . x | ex file.txt

編集する:実際に使用する必要はありませんq!。省略するだけでx変更の保存を避けることができます。ex追加の入力を読み取ろうとしたときにEOFが受信されると、変更を保存せずに終了します。

答え2

h試してみてください。行が一致したら、前のスペースにコピーしてs値を変更します。
緯度線の$保持空間とパターン空間を変更し、x後者が空であることを確認します。空でない場合は、すでに交換が完了していることを意味しますので、別の措置を講じる必要はありません。空の場合、一致する項目がないことを意味するため、パターン空間が置き換えられ、保持SMEAR=-5バッファの現在の行に追加されます。最後に、eはx再び変更されます。

sed '/SMEAR/{h;s/.*/SMEAR=-5/};${x;/^$/{s//SMEAR=-5/;H};x}' infile

上記はgnu sed構文です。持ち運べる:

sed '/SMEAR/{
h
s/.*/SMEAR=-5/
}
${
x
/^$/{
s//SMEAR=-5/
H
}
x
}' infile

代替方法ed:

ed -s infile<<\IN || printf %s\\n SMEAR=-5 >> infile
/SMEAR.*/s//SMEAR=-5/ 
w
q
IN

パターンに一致する行がないとedエラーが発生するため、printf...2番目のコマンド()が実行され、その行がファイルに追加されます。それ以外の場合、edファイルはその場所で編集されます。


SMEAR次の変数に値を保存すると、

var=-7

次を実行します。

sed '/SMEAR/{h;s/.*/SMEAR='"$var"'/};${x;/^$/{s//SMEAR='"$var"'/;H};x}' infile

または

ed -s infile<<IN || printf %s\\n "SMEAR=${var}" >> infile
/SMEAR.*/s//SMEAR=${var}/ 
w
q
IN

答え3

または実装ワイルドカードのアイデア (含まれているすべての既存の行を削除し、目的のSMEAR行を挿入します。)石器時代ツールを使用する:

(grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp  &&  cp file1.tmp file1  &&  rm file1.tmp

または、保存された属性(権限など)やハードリンクに興味がない場合は、file1次のことを実行できます。

(grep -v '^SMEAR=' file1; echo 'SMEAR=-5') > file1.tmp  &&  mv file1.tmp file1

または があればこれを行うspongeことができます。

(grep -v '^SMEAR=' file1; echo 'SMEAR=-5') | sponge file1

関連情報