Il file che hai mostrato ha tutti i dettagli su una riga:
name : farah age : 23 phone number : 0123 education : degree
Ho ipotizzato che sia possibile inserire un codice age :
nel codice ecc. Nel comando, ma il testo che segue varierà e che i dettagli potrebbero non essere nell'ordine dato o essere contigui.
Puoi estrarre parti della linea con grep
la -o
bandiera di. Questo stampa solo la parte abbinata, anziché l'intera linea.
Se si desidera includere le parti age :
e phone number :
, è possibile utilizzare il -e
flag per specificare più corrispondenze oppure alternare.
$ grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file
age : 23
phone number : 0123
L'espressione [^ ]*
indica un numero qualsiasi di caratteri che non sono uno spazio, quindi corrisponde ai caratteri dopo age :
fino allo spazio successivo.
Sostituisci file
con il nome del file che contiene i tuoi dettagli. È possibile scrivere il nuovo file reindirizzando l'output su un nuovo file con l' >
operatore, in questo modo:
grep -oe 'age : [^ ]*' -e 'phone number : [^ ]*' file > outfile
Quando lo fai, non vedrai alcun output. Dovresti prima controllare l'output, quindi aggiungere il reindirizzamento.
Ecco l'esempio con l'alternanza. Usiamo la -E
bandiera per dire grep
di usare regex esteso. La sintassi è (pattern1|pattern2)
: questo corrisponde pattern1
e / o pattern2
. Se viene trovato uno dei due, verrà stampato (indipendentemente dal fatto che l'altro venga trovato o meno). Ora sto usando il +
significato di almeno uno del carattere precedente, invece di *
indicare zero o più del carattere precedente. In questo contesto, entrambi funzionano ugualmente bene.
$ grep -Eo '(age : [^ ]+|phone number : [^ ]+)' file
age : 23
phone number : 0123
Se si desidera omettere le parti age :
e phone number:
, è possibile utilizzare la -P
bandiera per chiedere grep
di utilizzare espressioni regolari compatibili con Perl. Questo supporta l'alternanza e anche un modo per abbinare il testo dopo un determinato modello:
$ grep -Po '(age : \K[^ ]+|phone number : \K[^ ]+)' file
23
0123
Se si desidera formattare il testo in modo diverso, è possibile utilizzare sed
, ad esempio:
$ sed -r 's/.*(age) : ([^ ]*).*(phone number) : ([^ ]*).*/\1:\2 | \3:\4/' file
age:23 | phone number:0123
Questo dipende dal fatto di age
venire prima phone number
, quindi aggiusta di conseguenza se non è così. Se non puoi fare affidamento sull'ordine, puoi utilizzare questo comando molto contorto:
$ sed -r 's/(.*)(phone number : [^ ]+)(.*) .*/\2 \1\4/; s/(phone number) : ([^ ]+) .*(age) : ([^ ]+).*/\1: \2 | \3: \4/' file
phone number: 0123 | age: 23
Questo riorganizza la linea in modo che la phone number :
sezione venga prima su ogni riga, quindi effettua una seconda sostituzione per selezionare i dettagli desiderati. Devo la tecnica qui usata a questa risposta di Muru .
Note su sed
comandi non coperti da spiegazioni precedenti
-r
usa regex esteso per comandi più leggibili (GNU sed
capisce -E
con lo stesso significato)
s/old/new/
sostituire old
connew
(pattern)
salva pattern
in riferimento in seguito, con \1
o \2
etc (corrispondente all'ordine da sinistra a destra in cui si verificano i gruppi di acquisizione - nota che sed
conterrà solo fino a 7 di questi!).
.
qualsiasi carattere, quindi .*
rappresenta un numero qualsiasi di qualsiasi carattere.
;
separa i comandi, come nella shell.