Como duplicar cada linha e alterar os dígitos dentro de cada linha de maneira diferente no linux?

3

O arquivo de entrada se parece com:

1 0 0 000 3444
2 3 3 456 6875
3 0 0 023 3300
4 2 2 211 1000

primeiro: eu quero ter 2 cópias de cada linha:

1 0 0 000 3444
1 0 0 000 3444
2 3 3 456 6875
2 3 3 456 6875
3 0 0 023 3300
3 0 0 023 3300
4 2 2 211 1000
4 2 2 211 1000

segundo: na primeira cópia de cada linha 3 deve ser substituído por 2 e 4 deve ser substituído por 1 e na segunda cópia de cada linha, 3 deve ser substituído por 1 e 4 deve ser substituído por 2 (a primeira coluna é o nome das linhas e os números das linhas não devem mudar). Então, a saída final se torna:

1 0 0 000 2111
1 0 0 000 1222
2 2 2 156 6875
2 1 1 256 6875
3 0 0 022 2200
3 0 0 021 1100
4 2 2 211 1000
4 2 2 211 1000

alguma sugestão por favor? Eu tentei isso, mas não funciona:

awk '
      { tmp = $2; gsub("3", "2", $2); gsub("4", "1", $2); print}
      { $2 = tmp; gsub("3", "1", $2); gsub("4", "2", $2); print}
    ' < input > output
    
por zara 17.08.2016 / 18:44

3 respostas

2

Como dobrar cada linha: veja aqui ...
Quanto ao seu segundo pedido, basta salvar o primeiro campo e toda a linha em variáveis, em seguida, fazer a primeira mudança, definir o primeiro campo para o valor inicial e imprimir, em seguida, restaurar o conteúdo da linha, fazer a segunda mudança, definir o primeiro campo novamente para o valor inicial e impressão:

awk '{t=$1;l=$0;gsub(/3/, "2");gsub(/4/, "1");$1=t;print}
{$0=l;gsub(/3/, "1");gsub(/4/, "2");$1=t;print}' infile
    
por 13.04.2017 / 14:37
1

O Perl parece ser muito bom para esse tipo de coisa, pois tem um tr

embutido
$ perl -alne '
    @tmp=@F; 
    tr/34/21/ for @tmp[1..4]; print join " ", @tmp; 
    tr/34/12/ for @F[1..4]; print join " ", @F
  ' file
1 0 0 000 2111
1 0 0 000 1222
2 2 2 156 6875
2 1 1 256 6875
3 0 0 022 2200
3 0 0 021 1100
4 2 2 211 1000
4 2 2 211 1000
    
por 17.08.2016 / 20:26
1

Não é exatamente elegante, mas é possível com o GNU sed :

h              # save in hold
s_^[0-9]\{1,\} __ # remove first column
s_3_A_g        # change 3 and 4 to A and B
s_4_B_g
x              # swap with hold
s_ .*$__       # remove everything but first column
G              # append from hold
s_\n_ _        # join lines (with space)
h              # save in hold space again
s_A_2_g        # first output -> 2, 1
s_B_1_g
p              # print first line
g              # restore from hold 
s_A_1_g        # second output -> 1, 2
s_B_2_g
# end of script, second line printed automatically

Isso salva a primeira coluna (para que não seja alterada) e cria uma versão da linha com todos os 3s e 4s restantes alterados para As e Bs, respectivamente. Essa linha é usada para as duas saídas, primeiro com 2 e 1 , e vice-versa.

sed -f script.sed input > output

Isso pressupõe que sua entrada contém apenas números e espaços, ou seja. A e B ainda não aparecem lá.

    
por 17.08.2016 / 19:35