Come aggiungo una riga di testo al centro di un file usando bash?

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 objective è 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’è ansible tramite uno script bash? È qualcosa che sed o awk può fare? O farebbe volentieri la creatività di ricreare il file?

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, separandoli 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 con una riga contenente nameserver 127.0.0.1 , una nuova riga (la tua versione di sed potrebbe non supportare \n , nel qual caso sostituire la 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 che tu voglia inserire immediatamente dopo la linea di 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 sed
  • a mynewtext : comando che dice a sed di inserire il testo mynewtext dopo il pattern abbinato

awk '/^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 il modello su due righe, non sostituirlo dopo quel modello )

Questo potrebbe funzionare per te:

  sed -e '/nameserver/{x;/./b;x;h;i\nameserver 127.0.0.1' -e '}' resolv.conf 

O GNU sed:

 sed -e '0,/nameserver/{//i\nameserver 127.0.0.1' -e '}' resolv.conf 

Ecco una soluzione Perl:

perl -lne 'if (not $f and /^nameserver/){ print "nameserver 127.0.0.1"; $f=1 }; print' resolv.conf

  • -n loop su ogni riga del file di input, non stampare automaticamente ogni riga

  • -l rimuove le newline prima dell’elaborazione e le aggiunge nuovamente in seguito

  • -e esegue il codice perl

$f viene utilizzato come flag per indicare che la stringa del server dei nomi è già stata trovata