Gli amministratori di sistema utilizzano un numero incalcolabile di strumenti da riga di comando e probabilmente usi regolarmente i tre discussi in questo articolo:grep
, sed
e awk
. Ma conosci tutti i modi in cui puoi usarli per manipolare il testo? In caso contrario (o non sei sicuro), continua a leggere.
Prima di iniziare, ecco le origini dei nomi dei comandi:
grep
:Secondo Wikipedia, il nome "deriva daed
comando g/re/p (g ricerca locale di una r egular e xpression e p rint matching lines), che ha lo stesso effetto."ed
è un "editor di testo orientato alla riga". Anche per qualcuno a cui piace la riga di comando, la modifica dei file riga per riga sembra troppo antiquata, ma le persone dovevano iniziare con qualcosa in tempi antichi ).sed
:Il nome deriva dal suo uso principale, come s tream ndr itor.awk
:Il suo nome deriva dalle iniziali dei suoi autori (Aho, Weinberger e Kernighan). Se il nome Kernighan suona qualche campanello (gioco di parole) per te, è perché questo scienziato informatico canadese ha contribuito alla creazione di Unix e co-autore del primo libro sul linguaggio C.
È eccellente tracciare l'albero genealogico dei comandi, ma ciò che conta davvero è che questi comandi sono piuttosto utili per la manipolazione del testo.
Nei seguenti esempi, userò un file chiamato quotes.txt
per illustrare come utilizzare i comandi. Ecco il contenuto di questo file:
$ cat quotes.txt
"God does not play dice with the universe."
- Albert Einstein, The Born-Einstein Letters 1916-55
"Not only does God play dice but... he sometimes throws them where they cannot be seen."
- Stephen Hawking
"I regard consciousness as fundamental..."
- Max Planck
"The cosmos is within us. We are made of star-stuff. We are a way for the universe to know itself."
- Carl Sagan
"[T]he atoms or elementary particles themselves are not real; they form a world of potentialities or possibilities rather than one of things or facts."
- Werner Heisenberg
grep
Il modo più semplice per usare grep
è:
$ grep universe quotes.txt
"God does not play dice with the universe."
"The cosmos is within us. We are made of star-stuff. We are a way for the universe to know itself."
Questo esempio fornisce la stringa da cercare (universo) e il luogo in cui cercarla (quotes.txt).
Se ci sono spazi nella stringa che vuoi cercare, devi racchiuderla tra virgolette:
$ grep "the universe" quotes.txt
"God does not play dice with the universe."
"The cosmos is within us. We are made of star-stuff. We are a way for the universe to know itself."
Alcune varianti comuni quando si utilizza grep
sono:
- Ignora maiuscole/minuscole:
grep -i string-to-search filename
- Cerca in più file:
grep -i string-to-search *.txt
Puoi cercare un'espressione regolare:
$ grep "191[0-9]" quotes.txt
- Albert Einstein, The Born-Einstein Letters 1916-55
Se desideri abilitare i modelli regexp estesi per utilizzare simboli come +
, ?
o |
, puoi usare egrep
comando, che è una scorciatoia per aggiungere il -E
flag su grep
. Ciò ti consente anche di cercare più stringhe:
$ egrep -i "albe|hawk" quotes.txt
- Albert Einstein, The Born-Einstein Letters 1916-55
- Stephen Hawking
Per mostrare le righe che includono la parola "universo" più la riga successiva (per includere il nome dell'autore):
$ grep -i universe -A 1 quotes.txt
"God does not play dice with the universe."
- Albert Einstein, The Born-Einstein Letters 1916-55
--
"The cosmos is within us. We are made of star-stuff. We are a way for the universe to know itself."
- Carl Sagan
Come probabilmente puoi immaginare, potresti visualizzare di più righe passando un numero diverso. Oppure potresti mostrare le righe precedenti usando il flag -B
.
Finora ho mostrato grep
in esecuzione da solo, ma è molto comune averlo in una catena di comandi:
$ echo "Authors who mentioned 'universe'"; cat quotes.txt | grep -i universe -A 1 | grep "^-"
- Albert Einstein, The Born-Einstein Letters 1916-55
- Carl Sagan
[ Potresti anche essere interessato a leggere 11 comandi Linux senza i quali non posso vivere. ]
sed
Il mio uso preferito per sed
è sostituire le stringhe nei file. Ad esempio:
$ cat quotes.txt | sed 's/universe/Universe/g'
Questo sostituirà universe
con Universe
e invia il risultato a stdout . Il g
flag significa "sostituisci tutte le occorrenze della stringa in ogni riga".
Alcune variazioni per questo sono:
- Sostituisci la stringa solo se si trova nelle prime tre righe:
sed '1,3 s/universe/Universe/g' quotes.txt
- Sostituisci n -esima occorrenza di un modello in una riga (ad esempio, la seconda occorrenza):
sed 's/universe/Universe/2' quotes.txt
Questi esempi non modificano il file originale. Se vuoi sed
per modificare il file esistente, usa -i
:
$ sed -i 's/universe/Universe/g' quotes.txt
Se usi -i
flag, assicurati di sapere esattamente cosa e quante occorrenze sarà interessato, poiché modificherà il file originale. Per scoprirlo, puoi eseguire un grep
e cerca prima il modello.
[ Vuoi testare le tue capacità di amministratore di sistema? Fai una valutazione delle abilità oggi. ]
ok
Il awk
è molto potente e offre molte opzioni per l'elaborazione di file di testo.
La maggior parte delle situazioni in cui utilizzo awk
implicano l'elaborazione di file con una struttura (colonne) ragionevolmente prevedibile, incluso il carattere utilizzato come separatore di colonna.
Quando awk
elabora un file, divide ogni riga usando il "separatore di campo" (variabile interna FS
, che per impostazione predefinita è il carattere spazio). Ogni campo è assegnato a variabili posizionali ($1
contiene il primo campo, $2
contiene il secondo e così via. $0
rappresenta la riga intera).
Puoi anche applicare filtri a ciascuna riga. Ad esempio:
$ cat quotes.txt | awk '/universe/ { print NR " - " $0 }'
1 - "God does not play dice with the universe."
10 - "The cosmos is within us. We are made of star-stuff. We are a way for the universe to know itself."
I comandi passati a awk
usa le virgolette singole (è come passare un miniprogramma da interpretare):
- Il
/universe/
parte diceawk
per selezionare solo le linee che corrispondono a questo modello. - Il programma "principale" va tra parentesi graffe.
NR
è la variabile interna che contiene il numero del record corrente, ad esempio il numero di riga corrente.- Ho aggiunto il
" -"
stringa per l'estetica.
Le variabili interne in awk
sono:
NR
:il numero totale di record di input visti finora dal comandoNF
:il numero di campi nel record di input correnteFS
:Il separatore del campo di input (uno spazio per impostazione predefinita)
Ecco un esempio che utilizza un formato di file più "prevedibile":
$ cat /etc/passwd | awk '/nologin/ { FS=":"; print $1 }'
(output omitted)
...
redis
akmods
cjdns
haproxy
systemd-oom
In quest'ultimo esempio:
/nologin/
seleziona solo le righe che contengono questo modello.FS=": ";
imposta il separatore di campo su:
invece del valore predefinito (spazio).print $1
stampa il primo campo di ogni riga (considerando che il separatore è:
).
Ulteriori informazioni
Questi erano alcuni semplici esempi per l'utilizzo di grep
, sed
e awk
.
Se leggi man
pagine per ciascuna, noterai molti parametri aggiuntivi e usi per questi pratici comandi.
Per casi d'uso semplici e cose che fai solo una volta ogni tanto, è sempre bene avere strumenti come questi nella tua cassetta degli attrezzi.
Se l'azione richiesta è più complessa, vale la pena considerare se questi strumenti hanno ancora senso da utilizzare. Per un caso d'uso aziendale o per la gestione di "tutto come codice", consiglio di utilizzare Ansible. I moduli Ansible hanno caratteristiche simili che ti consentono di emulare le operazioni sopra descritte, con il vantaggio che i moduli Ansible di solito hanno idempotenza e che l'intero processo sarà documentato da qualche parte (come nel tuo repository Git interno).