it-swarm.dev

come rimuovere le prime due colonne in un file usando Shell (awk, sed, qualunque)

Ho un file con molte righein ogni riga ci sono molte colonne (campi) separate da bianco "" I numeri delle colonne in ogni riga sono diversi Voglio rimuovere le prime due colonne come?

64
wenzi

Puoi farlo con cut:

cut -d " " -f 3- input_filename > output_filename

Spiegazione:

  • cut: richiama il comando cut
  • -d " ": usa un singolo spazio come delimitatore (cut usa TAB per default)
  • -f: specifica i campi da conservare
  • 3-: tutti i campi che iniziano con il campo 3
  • input_filename: usa questo file come input
  • > output_filename: scrive l'output in questo file.

In alternativa, puoi farlo con awk:

awk '{$1=""; $2=""; sub("  ", " "); print}' input_filename > output_filename

Spiegazione:

  • awk: invoca il comando awk
  • $1=""; $2="";: imposta il campo 1 e 2 sulla stringa vuota
  • sub(...);: ripulisci i campi di output perché i campi 1 e 2 saranno ancora delimitati da ""
  • print: stampa la riga modificata
  • input_filename > output_filename: come sopra.
130
sampson-chen

Ecco un modo per farlo con Awk che è relativamente facile da capire:

awk '{print substr($0, index($0, $3))}'

Questo è un semplice comando awk senza pattern, quindi l'azione all'interno di {} viene eseguita per ogni riga di input. 

L'azione consiste nel stampare semplicemente la sottostringa che inizia con la posizione del terzo campo.

  • $0: l'intera riga di input
  • $3: 3 ° campo
  • index(in, find): restituisce la posizione di find nella stringa in
  • substr(string, start): restituisce una sottostringa a partire da index start

Se si desidera utilizzare un delimitatore diverso, ad esempio una virgola, è possibile specificarlo con l'opzione -F:

awk -F"," '{print substr($0, index($0, $3))}'

Puoi anche operare su un sottoinsieme delle linee di input specificando un pattern prima dell'azione in {}. Solo le linee che corrispondono al modello eseguiranno l'azione.

awk 'pattern{print substr($0, index($0, $3))}'

Dove pattern può essere qualcosa come:

  • /abcdef/: usa l'espressione regolare, opera su $ 0 per impostazione predefinita.
  • $1 ~ /abcdef/: opera su un campo specifico.
  • $1 == blabla: usa il confronto delle stringhe
  • NR > 1: utilizza il numero di record/linea
  • NF > 0: usa il campo/numero di colonna
21
raychi

Grazie per aver postato la domanda. Mi piacerebbe anche aggiungere la sceneggiatura che mi ha aiutato.

awk '{ $1=""; print $0 }' file
12
Felipe Alvarez
awk '{$1=$2="";$0=$0;$1=$1}1'

Ingresso

a b c d

Produzione

c d
8
Steven Penny

È abbastanza semplice farlo solo con Shell

while read A B C; do
echo "$C"
done < oldfile >newfile
6
technosaurus

Puoi usare sed:

sed 's/^[^ ][^ ]* [^ ][^ ]* //'

Questo cerca le linee che iniziano con uno o più bianchi, uno spazio vuoto, un altro insieme di uno o più non bianchi e un altro vuoto, e cancella il materiale corrispondente, ovvero i primi due campi. Il [^ ][^ ]* è leggermente più corto della notazione equivalente [^ ]\{1,\} equivalente, e il secondo potrebbe incorrere in problemi con GNU sed (anche se si usa --posix come opzione, anche GNU sed non può rovinarlo su). OTOH, se la classe di caratteri da ripetere era più complessa, la notazione numerata vince per brevità. È facile estenderlo per gestire "vuoto o tabulazione" come separatore o "più spazi vuoti" o "più spazi vuoti o tabulazioni". Potrebbe anche essere modificato per gestire spazi vuoti iniziali (o tabulazioni) prima del primo campo, ecc.

Per awk e cut, vedere Sampson-Chen 's answer . Ci sono altri modi per scrivere lo script awk, ma non sono materialmente migliori della risposta data. Si noti che potrebbe essere necessario impostare esplicitamente il separatore di campo (-F" ") in awk se non si desidera che le schede vengano considerate come separatori oppure si potrebbero avere più spazi vuoti tra i campi. Lo standard POSIX cut non supporta più separatori tra i campi; GNU cut ha l'opzione -i utile ma non standard per consentire separatori multipli tra i campi.

Puoi anche farlo in puro Shell:

while read junk1 junk2 residue
do echo "$residue"
done < in-file > out-file
6
Jonathan Leffler

Perl:

Perl -lane 'print join(' ',@F[2..$#F])' File

awk:

awk '{$1=$2=""}1' File
4
Vijay

Questo potrebbe funzionare per te (GNU sed):

sed -r 's/^([^ ]+ ){2}//' file

o per colonne separate da uno o più spazi bianchi:

sed -r 's/^(\S+\s+){2}//' file
1
potong

Usando awk e basato su alcune delle opzioni seguenti, l'uso di un ciclo for rende un po 'più flessibile; a volte vorrei eliminare le prime 9 colonne (se faccio un "ls -lrt" per esempio), quindi cambio il 2 per un 9 e basta:

awk '{ for(i=0;i++<2;){$i=""}; print $0 }' your_file.txt

0
Carlos

Usa kscript

kscript 'lines.split().select(-1,-2).print()' file
0
Holger Brandl