Apare um campo específico e substitua no Unix Shell Script

1

Eu tenho um arquivo com os dados abaixo:

5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222222222222222222222222222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|88888888888888888888888888888|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222222222222222222222222222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|55555555555555555555555555555|ABCD|AB|30

Os dados são separados por um caractere de controle-A, mas eu os substituí aqui por | , já que não pude postar dados com o controle-A.

Eu quero cortar o valor de 22222222222222222222222222222 e desejar o primeiro valor de 5 para que nossos dados de saída final sejam assim:

5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|88888|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|55555|ABCD|AB|30

Procurando alguma ajuda nisso.

    
por Sandeep Singh 27.01.2016 / 14:26

3 respostas

2

Você poderia fazer isso com awk da seguinte forma:

awk -F\| 'BEGIN {OFS="|"};{$12=substr($12,1,5)};1' 

-F define o separador de campo como | , em seguida, antes de começar a processar o texto, usamos o bloco BEGIN para definir o separador do campo de saída ( OFS ) como | . Em seguida, substituímos o valor no 12º campo pelos 5 primeiros caracteres desse campo para cada registro.

Você pode dar o nome do arquivo para processar como outro argumento na linha de comando, que é o que você provavelmente quer, ou usar isso em um pipeline se você tiver um processo que esteja gerando o arquivo que deseja atualizar.

Obrigado ao Stéphane Chazelas por corrigir alguns problemas que tive e torná-lo mais POSIX-y. Em particular, para corrigir meu índice inicial de 0 a 1. A documentação do GNU inclui a seguinte linha que me deixa escapar do erro:

If start is less than one, substr() treats it as if it was one.

mas 1 é o índice do primeiro caractere, e por isso deve ser usado, especialmente para pessoas que não usam gawk . Por exemplo, com mawk :

$ mawk 'BEGIN{print substr("1234567", 0, 5)}'
1234
$ mawk 'BEGIN{print substr("1234567", 1, 5)}'
12345
    
por 27.01.2016 / 14:38
2

com awk :

awk 'BEGIN{FS=OFS=""}; {$12=substr($12,1,5)}; 1' file
  • BEGIN{...} : é executado antes do processamento ser iniciado
  • FS=OFS="" : define o separador de campo de entrada e saída como ^A . De acordo com Wikcionário ^A é o "primeiro caractere de um cabeçalho de mensagem", cujo valor de octal é 1 .
  • {$12=substr($12,1,5)} : apara o 12º campo.
  • 1 : imprime (ação padrão) o registro.
por 27.01.2016 / 14:39
0
sed 's/\([^|]\{0,5\}\)[^|]*//12' <in >out

... ou w / a GNU ou BSD sed :

sed -E 's/([^|]{0,5})[^|]*//12' <in >out
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|88888|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|22222|ABCD|AB|30
5773|2015-11-19|2016418|O|2015-11-06|C|AB1CD|826|826|CDE|2015-11-19|55555|ABCD|AB|30

É bastante simples: da 12ª ocorrência possível em uma linha de entrada de uma seqüência de qualquer número de caracteres não-pipe, reter apenas um máximo de 5.

    
por 27.01.2016 / 18:25