Come troncare la seconda colonna a una determinata lunghezza


9

Dato input del modulo

XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar foolkasjfdrte

come posso troncare solo la seconda colonna? Il delimitatore è TAB e la seconda colonna deve contenere al massimo 75 caratteri.


Un po 'più generico:awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
fedorqui,

Vuoi troncare (eliminare i caratteri dopo il 75 °) o piegare (stamparli su un'altra riga)? Inoltre, gli spazi devono essere conteggiati verso i 75 caratteri o no?
terdon

Risposte:


7

Se si desidera stampare solo i primi 75 caratteri della seconda colonna (inclusi gli spazi e presupponendo solo due colonne nel file), è possibile eseguire:

$ perl -pe 's/(\t.{75}).*/$1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Oppure, con GNU sed:

$ sed 's/\(.*\t.\{75\}\).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

O:

$ sed -r 's/(.*\t.{75}).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

In alternativa, puoi usare fold, dicendo di tagliare i primi 91 caratteri (che sono 8 per l'identificatore e altri 8 per la scheda) e stampare solo la prima riga:

$ fold -w 91 file | head -n1
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Se il tuo file può contenere più di 2 colonne e vuoi solo troncare la seconda, puoi farlo (che, come ho appena notato, è solo una riformulazione della risposta di Stephen ):

$ awk -F"\t" -vOFS="\t" '{$2=substr($2,1,75)}1;' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Oppure (notare che questo si interromperà se i primi 75 caratteri della seconda colonna possono essere interpretati come un'espressione regolare):

$ perl -F"\t" -pale 's/$F[1]/substr($F[1],0,75)/e' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Quelli possono troncare un'altra colonna rispetto alla seconda. Il tuo primo sedcomando utilizza anche un GNUism ( \t).
Stéphane Chazelas,

@ StéphaneChazelas cosa ? \tè un GNUismo? Sul serio? Qual è il modo portatile di descrivere una scheda allora?
terdon

1
Inseriscilo alla lettera per vedere la mia risposta. L'unica sequenza di escape riconosciuta in modo portabile su LHS è \n(e di nuovo non all'interno [...]con molte implementazioni), nessuna su RHS.
Stéphane Chazelas,

@ StéphaneChazelas accidenti, grazie. Ho anche aggiunto una soluzione in grado di gestire più colonne.
terdon

Il tuo ultimo perlha poco senso. Pensa ad esempio a un input comeaba\t.*
Stéphane Chazelas,

10

Usando awk, dividi il file usando le schede e genera il primo campo per intero e i primi 75 caratteri (al massimo) del secondo:

awk -F "\t" 'BEGIN { OFS=FS }; { print $1, substr($2, 1, 75); }'

Come sottolineato da fedorqui , puoi gestire i file con più di due campi sostituendo i campi che devi troncare:

awk -F "\t" 'BEGIN { OFS=FS }; { $2=substr($2, 1, 75); print }'

È possibile applicare substra più campi eseguendo il ciclo su di essi, se necessario.


@ Stéphane, in quali casi sono ;necessari extra ?
Stephen Kitt,

Sono richiesti da POSIX. Ora non conosco alcuna implementazione in cui siano richiesti, ma quando ho chiesto che quel requisito POSIX fosse rilassato, è stato rifiutato dal manutentore gawk (dove tutti gli esempi nel documento hanno il;).
Stéphane Chazelas,

Ah, buono a sapersi, grazie! Quindi le specifiche e la documentazione sono più rigorose di tutte le implementazioni ...
Stephen Kitt,

tutte le implementazioni che conosco almeno (non così tante). Il punto è omettere il delimitatore per una sintassi non standard. Quindi le implementazioni attuali e future possono e hanno il diritto di soffocare su di esso o introdurre estensioni che ne fanno uso (come un'eccezione che ne gestisce una /pattern/ {action} {exception-handling}ad esempio). Ora sarebbe estremamente improbabile dato che omettere quelli ;è abbastanza comune.
Stéphane Chazelas,

4

Portabilmente / POSIX con sed:

tab=$(printf '\t')
sed "s/\($tab[^$tab]\{0,75\}\)[^$tab]*/\1/"

O per troncare ogni colonna:

sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"

2

Se ci sono solo 2 colonne:

sed -r 's/^([^\t]*\t)(.{0,75}).*/\1\2/'

{0,75}significa selezionare da 0 a 75 caratteri.
.* è la sezione rimossa oltre il carattere 75.


Se ci sono 2 o più colonne:

sed -r 's/^([^\t]*\t)([^\t]{0,75})[^\t]*(.*)/\1\2\3/' file

[^\t]* è la sezione rimossa oltre il carattere 75.


Si noti che ciò presuppone GNU sede che POSIXLY_CORRECTnon è nell'ambiente ..
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.