Sto provando ad estrarre un certo (il quarto) campo dal stream di testo adattato alle colonne e adattato allo spazio. Sto cercando di utilizzare il comando di cut
nel modo seguente:
cat text.txt | cut -d " " -f 4
Sfortunatamente, il cut
non considera più spazi come un delimitatore. Avrei potuto trasmettere attraverso awk
awk '{ printf $4; }'
o sed
sed -E "s/[[:space:]]+/ /g"
per far crollare gli spazi, ma mi piacerebbe sapere se esiste un modo per gestire nativamente il cut
e diversi delimitatori?
Provare:
tr -s ' '
Dalla pagina tr
man:
-s, --squeeze-repeat sostituisce ogni sequenza di input di un carattere ripetuto quello è elencato in SET1 con una singola occorrenza di quel personaggio
Mentre commentate la vostra domanda, awk
è davvero la strada da percorrere. Usare il cut
è ansible insieme a tr -s
per spremere gli spazi, come mostra la risposta di kev .
Lasciatemi comunque passare attraverso tutte le possibili combinazioni per i futuri lettori. Le spiegazioni sono nella sezione Test.
tr -s ' ' < file | cut -d' ' -f4
awk '{print $4}' file
while read -r _ _ _ myfield _ do echo "forth field: $myfield" done < file
sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file
Dato questo file, proviamo i comandi:
$ cat a this is line 1 more text this is line 2 more text this is line 3 more text this is line 4 more text
$ cut -d' ' -f4 a is # it does not show what we want! $ tr -s ' ' < a | cut -d' ' -f4 1 2 # this makes it! 3 4 $
$ awk '{print $4}' a 1 2 3 4
Questo legge i campi in modo sequenziale. Usando _
indichiamo che questa è una variabile usa e getta come "variabile spazzatura" per ignorare questi campi. In questo modo, archiviamo $myfield
come il 4 ° campo nel file, indipendentemente dagli spazi tra loro.
$ while read -r _ _ _ a _; do echo "4th field: $a"; done < a 4th field: 1 4th field: 2 4th field: 3 4th field: 4
Questo cattura tre gruppi di spazi e nessuno spazio con ([^ ]*[ ]*){3}
. Quindi, cattura qualsiasi cosa arrivi fino a uno spazio come il 4 ° campo, che viene infine stampato con \1
.
$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a 1 2 3 4
Dopo essere stato frustrato dalle troppe limitazioni di cut
, ho scritto il mio sostituto, che ho chiamato cuts
per “tagliare con gli steroidi”.
tagli fornisce quella che è probabilmente la soluzione più minimalista per questo e molti altri problemi relativi al taglia / incolla.
Un esempio, tra tanti, che affronta questa particolare domanda:
$ cat text.txt 0 1 2 3 0 1 2 3 4 $ cuts 2 text.txt 2 2
supporti per cuts
:
paste
separatamente) e altro ancora. Nessuno dei quali è fornito dal cut
standard.
Vedi anche: https://stackoverflow.com/a/24543231/1296044
Fonte e documentazione (software libero): http://arielf.github.io/cuts/
Questo one-liner Perl mostra quanto strettamente Perl sia correlato a awk:
perl -lane 'print $F[3]' text.txt
Tuttavia, l’array autosplit @F inizia all’indice $F[0]
mentre i campi awk iniziano con $1
Con le versioni di cut
che conosco, no, questo non è ansible. cut
è utile principalmente per analizzare i file in cui il separatore non è uno spazio bianco (ad esempio /etc/passwd
) e che hanno un numero fisso di campi. Due separatori in una riga indicano un campo vuoto, e questo vale anche per gli spazi vuoti.