a variável shell no awk não está sendo passada para todas as linhas, mas apenas para a primeira linha de entrada?

2

inputfile: is2.txt

10.39.5.41,A1,B1
10.39.5.41,A2,B2
10.39.5.41,A3,B3
10.39.5.41,A4,B4
10.39.5.41,A5,B5
10.39.5.41,A6,B6

script:

#!/bin/bash
second_column="OOOOOOO"    # OOOOOOO will be added to every second column
third_column="XXXXXXXX"    # XXXXXXXX will be added to every third column

awk -v second="$second_column" -v third="$third_column" 'BEGIN { FS="," }
                             {
                                if(a[$1])
                                {a[$1]=a[$1]";second"$2";third"$3}
                                 else
                                {a[$1]=a[$1]second$2";"third$3}}
                             END{for (i in a)print i";"a[i];}' <  is2.txt

output:
[root@testgfs2 test]# ./testawk.awk
10.39.5.41;OOOOOOOA1;XXXXXXXXB1;secondA2;thirdB2;secondA3;thirdB3;secondA4;thirdB4;secondA5;thirdB5;secondA6;thirdB6

porque as variáveis do shell (second_column, third_column) não estão sendo refletidas para a saída completa e apenas para a primeira linha. O que há de errado?

resultado esperado:

10.39.5.41;OOOOOOOA1;XXXXXXXXB1;OOOOOOOA2;XXXXXXXXB2;OOOOOOOA3;XXXXXXXXB3;OOOOOOOA4;XXXXXXXXB4;OOOOOOOA5;XXXXXXXXB5;OOOOOOOA6;XXXXXXXXB6

Além disso, existe alguma maneira de generalizar isso para n número de colunas, digamos n = 100?

    
por munish 25.02.2013 / 14:42

1 resposta

5

Aqui está o código awk com espaçamento recomendado e indention, você consegue ver o problema?

BEGIN { FS = "," }

{
  if(a[$1])
    a[$1] = a[$1] ";second" $2 ";third" $3
  else
    a[$1] = a[$1]second $2 ";" third$3
}

END {
  for (i in a)
    print i ";" a[i]
}

Você citou second e third na cláusula if .

Adivinhando a saída esperada, você pode fazer assim:

awk -v c2='OOOOOOO' -v c3='XXXXXXXX' -v FS=, -v OFS=';' -v ORS=';' '
  !f { 
    printf "%s", $1
    f=1
  } 
  {
    $1 = ""
    $2 = c2 $2
    $3 = c3 $3
  } 
  1
' | sed 's/;;/;/g; s/;$//'

Saída:

10.39.5.41;OOOOOOOA1;XXXXXXXXB1;OOOOOOOA2;XXXXXXXXB2;OOOOOOOA3;XXXXXXXXB3;OOOOOOOA4;XXXXXXXXB4;OOOOOOOA5;XXXXXXXXB5;OOOOOOOA6;XXXXXXXXB6

Para generalizar essa abordagem, você poderia passar os bits para preceder através de uma string e dividi-la em uma matriz awk. Em seguida, use um loop for em vez de variáveis de coluna explícitas:

awk -v prepends='OOOOOOO XXXXXXXX' -v FS=, -v OFS=';' -v ORS=';' '
  BEGIN { split(prepends, cn, / +/) } 

  !f { 
    printf "%s", $1
    f=1
  } 

  { 
    $1 = ""
    for(i=1; i<=NF; i++) 
      $i = cn[i-1] $i
  }
  1' | sed 's/;;/;/g; s/;$//'
    
por 25.02.2013 / 15:20