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.


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

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.


@ 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"

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.


Note que que assume GNU sede que POSIXLY_CORRECTnão está no ambiente ..
Stéphane Chazelas
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.