Como truncar a segunda coluna para determinado comprimento

9

Entrada dada do formulário

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

como posso truncar apenas a segunda coluna? O delimitador é TAB e a segunda coluna deve ter no máximo 75 caracteres.

LoukiosValentine79
fonte
Um pouco mais genérico:awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
fedorqui
Deseja truncar (excluir caracteres após o 75º) ou dobrar (imprimi-los em outra linha)? Além disso, os espaços devem ser contados para os 75 caracteres ou não?
terdon

Respostas:

7

Se você deseja imprimir apenas os primeiros 75 caracteres da segunda coluna (incluindo espaços e assumindo apenas duas colunas no arquivo), você pode:

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

Ou, com o 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

Como alternativa, você pode usar fold, dizendo para cortar os 91 primeiros caracteres (8 para o identificador e 8 para a guia) e imprimir apenas a primeira linha:

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

Se o seu arquivo pode ter mais de 2 colunas e você deseja apenas truncar a segunda, você pode fazer (o que, como acabei de notar, é apenas uma reformulação da resposta 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 (observe que isso será interrompido se os primeiros 75 caracteres da 2ª coluna puderem ser interpretados como uma expressão regular):

$ 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
fonte
Esses podem truncar outras colunas além da segunda. Seu primeiro sedcomando também está usando um GNUism ( \t).
Stéphane Chazelas
@ StéphaneChazelas what ? \tque é um GNUism? A sério? Qual é a maneira portátil de descrever uma guia então?
terdon
1
Insira-o literalmente de veja minha resposta. A única sequência de escape reconhecida de maneira portável no LHS é \n(e novamente não está presente [...]com muitas implementações), nenhuma no RHS.
Stéphane Chazelas
@ StéphaneChazelas droga, obrigado. Eu também adicionei uma solução que pode lidar com várias colunas.
terdon
Seu último perlfaz pouco sentido. Pense, por exemplo, em uma entrada comoaba\t.*
Stéphane Chazelas
10

Usando awk, divida o arquivo usando guias e produza o primeiro campo completo e os primeiros 75 caracteres (no máximo) do segundo:

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

Conforme apontado por fedorqui , você pode manipular arquivos com mais de dois campos, substituindo os campos que você precisa truncar:

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

Você pode aplicar a substrvários campos fazendo um loop sobre eles, se necessário.

Stephen Kitt
fonte
@ Stéphane, em que casos os extras são ;necessários?
Stephen Kitt
Eles são requeridos pelo POSIX. Agora não conheço nenhuma implementação em que elas são necessárias, mas quando solicitei que o requisito POSIX fosse relaxado, ele foi rejeitado pelo mantenedor do gawk (onde todos os exemplos no documento têm o;).
Stéphane Chazelas
Ah, bom saber, obrigado! Portanto, as especificações e a documentação são mais rigorosas do que todas as implementações ...
Stephen Kitt
todas as implementações que eu conheço, pelo menos (não tantas). O ponto é omitir o delimitador cria sintaxe não padrão. Portanto, as implementações atuais e futuras podem e têm o direito de se engasgar com ela ou introduzir extensões que a utilizem (como uma exceção que lida com uma, /pattern/ {action} {exception-handling}por exemplo). Agora, isso seria extremamente improvável, uma vez que omitir essas informações ;é bastante comum.
Stéphane Chazelas
4

Portably / POSIXly com sed:

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

Ou para truncar todas as colunas:

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

Se houver apenas 2 colunas:

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

{0,75}significa selecionar de 0 a 75 caracteres.
.* é a seção removida além do caractere 75.


Se houver 2 ou mais colunas:

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

[^\t]* é a seção removida além do caractere 75.

Peter.O
fonte
Note que que assume GNU sede que POSIXLY_CORRECTnão está no ambiente ..
Stéphane Chazelas