it-swarm-eu.dev

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 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?

35
PHLAK

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
39
brandizzi

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 sed
  • a mynewtext: comando che dice a sed di inserire il testo mynewtext dopo il pattern abbinato
19
Jim Garrison

awk '/^nameserver/ && !modif { printf("INSERT\n"); modif=1 } {print}'

8
Karoly Horvath

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 )

2
sagi

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

0
Chris Koknat

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
0
potong