Sto cercando di aggiungere una riga di testo al centro di un file di testo in uno script bash. Specificamente sto provando ad aggiungere un nameserver al mio file /etc/resolv.conf. Così com'è, resolv.conf si presenta così:
# Generated by NetworkManager
domain dhcp.example.com
search dhcp.example.com
nameserver 10.0.0.1
nameserver 10.0.0.2
nameserver 10.0.0.3
Il mio obiettivo è aggiungere nameserver 127.0.0.1
sopra tutte le altre righe del nameserver, ma al di sotto di qualsiasi testo sopra quello. Alla fine voglio che il mio file resolve.conf assomigli a questo:
# Generated by NetworkManager
domain dhcp.example.com
search dhcp.example.com
nameserver 127.0.0.1
nameserver 10.0.0.1
nameserver 10.0.0.2
nameserver 10.0.0.3
Com'è possibile tramite uno script bash? È qualcosa che sed o awk può fare? O la grep creativa dovrebbe ricreare il file è la mia mossa migliore?
Ecco una soluzione che usa sed:
$ sed -n 'H;${x;s/^\n//;s/nameserver .*$/nameserver 127.0.0.1\n&/;p;}' resolv.conf
# Generated by NetworkManager
domain dhcp.example.com
search dhcp.example.com
nameserver 127.0.0.1
nameserver 10.0.0.1
nameserver 10.0.0.2
nameserver 10.0.0.3
Come funziona: in primo luogo, sopprimere l'output di sed con il flag -n
. Quindi, per ogni riga, aggiungiamo la linea allo spazio di attesa, separandole con nuove linee:
H
Quando arriviamo alla fine del file (indirizzato da $
) spostiamo il contenuto dello spazio di attesa nello spazio pattern:
x
Se la prima riga nello spazio modello è vuota, la sostituiamo con nulla.
s/^\n//
Quindi sostituiamo la prima riga che inizia con nameserver
da una riga contenente nameserver 127.0.0.1
, una nuova riga (la tua versione di sed
potrebbe non supportare \n
, nel qual caso sostituire n
con una nuova riga letterale) e la linea originale (rappresentata da &
):
s/nameserver .*$/nameserver 127.0.0.1\n&/
Ora abbiamo solo bisogno di stampare i risultati:
p
Supponendo di voler inserire immediatamente dopo la riga search
, questo è molto più semplice:
sed -ie '/^search/a nameserver 127.0.0.1' filename
-i
: modifica il file in posizione-e
: consente l'esecuzione di uno script/comandi all'interno dell'espressione seda mynewtext
: comando che dice a sed di inserire il testo mynewtext dopo il pattern abbinatoawk '/^nameserver/ && !modif { printf("INSERT\n"); modif=1 } {print}'
Che ne dici di qualcosa come:
sed -e ':a;N;$!ba;s/nameserver/nameserver 127.0.0.1\nnameserver/' /etc/resolv.conf
(simile a questo: sed: Trova pattern su due righe, non sostituirlo dopo quel pattern )
Ecco una soluzione Perl:
Perl -lne 'if (not $f and /^nameserver/){ print "nameserver 127.0.0.1"; $f=1 }; print' resolv.conf
-n
fa il giro di ogni riga del file di input, non stampa automaticamente ogni riga
-l
rimuove le newline prima dell'elaborazione e le aggiunge nuovamente in seguito
-e
esegue il codice Perl
$f
è usato come flag per indicare che la stringa del server dei nomi è già stata trovata
Questo potrebbe funzionare per te:
sed -e '/nameserver/{x;/./b;x;h;i\nameserver 127.0.0.1' -e '}' resolv.conf
Oppure GNU sed:
sed -e '0,/nameserver/{//i\nameserver 127.0.0.1' -e '}' resolv.conf