Comment tronquer la deuxième colonne à une longueur donnée

9

Compte tenu de la saisie du formulaire

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

comment puis-je tronquer uniquement la deuxième colonne? Le délimiteur est TAB et la deuxième colonne doit contenir au plus 75 caractères.

LoukiosValentine79
la source
Un peu plus générique:awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
fedorqui
Voulez-vous tronquer (supprimer les caractères après le 75) ou les plier (les imprimer sur une autre ligne)? De plus, les espaces doivent-ils être comptés dans les 75 caractères ou non?
terdon

Réponses:

7

Si vous souhaitez imprimer uniquement les 75 premiers caractères de la deuxième colonne (y compris les espaces et en supposant que deux colonnes dans le fichier), vous pouvez faire:

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

Ou, avec GNU sed:

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

Ou:

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

Alternativement, vous pouvez utiliser fold, en lui disant de couper les 91 premiers caractères (c'est 8 pour l'identifiant et 8 autres pour l'onglet), et en imprimant uniquement la première ligne:

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

Si votre fichier peut avoir plus de 2 colonnes et que vous souhaitez seulement tronquer la seconde, vous pouvez le faire (ce qui, comme je viens de le remarquer, n'est qu'une reformulation de la réponse de Stephen ):

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

Ou (notez que cela se cassera si les 75 premiers caractères de la 2ème colonne peuvent être interprétés comme une expression régulière):

$ 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
terdon
la source
Ceux-ci peuvent tronquer une autre colonne que la seconde. Votre première sedcommande utilise également un GNUism ( \t).
Stéphane Chazelas
@ StéphaneChazelas quoi ? \t'est-ce qu'un GNUisme? Sérieusement? Quelle est la manière portable de décrire un onglet alors?
terdon
1
Insérez-le mot pour voir ma réponse. La seule séquence d'échappement reconnue de manière portable sur le LHS est \n(et encore une fois pas à l'intérieur [...]avec de nombreuses implémentations), aucune sur le RHS.
Stéphane Chazelas
@ StéphaneChazelas putain, merci. J'ai également ajouté une solution qui peut gérer plusieurs colonnes.
terdon
Votre dernier perln'a pas de sens. Pensez par exemple à une entrée commeaba\t.*
Stéphane Chazelas
10

À l'aide de awk, divisez le fichier à l'aide d'onglets et affichez le premier champ dans son intégralité et les 75 premiers caractères (au plus) du second:

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

Comme l'a souligné Fedorqui , vous pouvez gérer des fichiers avec plus de deux champs en remplaçant les champs que vous devez tronquer:

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

Vous pouvez appliquer le substrà plusieurs champs en les bouclant si nécessaire.

Stephen Kitt
la source
@ Stéphane, dans quels cas le supplément est-il ;nécessaire?
Stephen Kitt
Ils sont requis par POSIX. Maintenant, je ne connais aucune implémentation où ils sont requis, mais quand j'ai demandé que cette exigence POSIX soit assouplie, elle a été rejetée par le responsable de gawk (où tous les exemples dans le document ont le;).
Stéphane Chazelas
Ah, bon à savoir, merci! La spécification et la documentation sont donc plus strictes que toutes les implémentations ...
Stephen Kitt
toutes les implémentations que je connais au moins (pas tellement). Le fait d'omettre le délimiteur crée une syntaxe non standard. Ainsi, les implémentations actuelles et futures peuvent et ont le droit de s'étouffer dessus ou d'introduire des extensions qui en font usage (comme une exception qui en gère une /pattern/ {action} {exception-handling}par exemple). Maintenant, ce serait extrêmement improbable étant donné que leur omission ;est assez courante.
Stéphane Chazelas
4

Portable / POSIXly avec sed:

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

Ou pour tronquer chaque colonne:

sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"
Stéphane Chazelas
la source
2

S'il n'y a que 2 colonnes:

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

{0,75}signifie sélectionner de 0 à 75 caractères.
.* est la section supprimée au-delà du caractère 75.


S'il y a 2 colonnes ou plus :

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

[^\t]* est la section supprimée au-delà du caractère 75.

Peter.O
la source
Notez que cela suppose GNU sedet que ce POSIXLY_CORRECTn'est pas dans l'environnement ..
Stéphane Chazelas