Come posso automatizzare la modifica delle coppie chiave / valore in uno script di shell?


3

Spesso voglio automatizzare questo tipo di attività in uno script di shell:

se la linea:

SOMEKEY=SOMEVALUE

esiste in un file, quindi cambiarlo in

SOMEKEY=SOMEOTHERVALUE

in caso contrario, aggiungere la riga SOMEKEY=SOMEOTHERVALUEnel file.

Come ho potuto fare questo? Penso che potrei farlo usando una combinazione di grepe sed, ma sono sicuro che sia un compito abbastanza comune che qualcuno abbia già elaborato una soluzione elegante.

A proposito, in sostituzione normalmente farei qualcosa del genere

sed -i 's/old/new/g' fname

Ma significa che devo stare molto attento quando compongo le mie espressioni regolari, in modo da non sbagliare. Esiste un modo semplice per "visualizzare in anteprima" quali modifiche si verificherebbero dalla mia chiamata sedsenza realmente calpestare il file?

Risposte:


1

Userei awk per questo compito:

   awk -F'=' -v "keyname=$SOMEKEY" -v "value=$SOMEOTHERVALUE" '
            $1 == keyname {
                    if ($2 != value) $2 = "\"" value "\""
                    key_found = 1
            }

            { print $1 "=" $2 }

            END { if (!key_found) print keyname "=\"" value "\"" }
   ' fname

supponendo

 SOMEKEY=key1
 SOMEOTHERVALUE="John Doe is dead!"

e dato questo input:

 key1="John Doe is geat!
 key2="Who's John Wayne?"

Uno ottiene:

 key1="John Doe is dead!"
 key2="Who's John Wayne?"

O se non key1è presente alcuna riga, key1="John Doe is dead!"verrà aggiunto alla fine.

Nota: su Solaris o altri derivati ​​UNIX che contengono ancora una vecchia versione di awk (1) , è necessario utilizzare nawk (1) .


Ho perso l'ultima domanda: se vuoi solo visualizzare l'anteprima delle modifiche, ometti l'opzione -ie il codice: yoursedcommand |grep fname - che confronterà l'esito del tuo comando con il file originalefname
ktf

ho provato, ad esempio, sed 's/HISTSIZE/SPAM/g' ~/.bashrc | grep ~/.bashrcma non ho visto alcun output.
mercoledì

Mi dispiace, stupido errore di battitura (ovviamente stavo pensando a qualcos'altro ...) Corretto è: yoursedcmd | diff fname -
ktf

sì, pensavo che avresti potuto significare diff, ma quando ho provato a ottenere diff: missing operand after / home / wim / .bashrc'``
wim

Non dimenticare il secondo argomento per diff : è solo un singolo segno meno ( -) che indica che il secondo file per il confronto deve essere letto da stdin
ktf,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.