Imprimindo campos usando o awk

1
< pool.sam awk '
  /./ {printf $1}
  {printf $7+1,"\t"}
  {printf $3,"\t"}
  {
    if($2 !=16) {print "\t", "+";} else {print "\t","-";}
    {printf $4,"\t" ,length($10)+$4, "\t", "1"}
  }'

Estou obtendo todos os valores, mas de uma maneira estranha. Estou imprimindo 7 valores,

valor1 valor2 valor3 valor7

Eu quero todos esses 7 valores, separados por um TAB, em cada linha.

Eu tentei o meu melhor para descobrir se usar print ou usar printf Parece que eu perdi isso.

Por favor, me guie.

    
por Death Metal 11.10.2013 / 08:09

2 respostas

2

Embora printf seja uma função impressa formatada , print concatena parâmetros.

Parece que você precisa verificar a função printf (ou ambos).

Em resumo, é:

printf <format, <parameter1>[, <parameter2>, ...] | text>

A letra % em um formato denota aqui vem um parâmetro que deve ser formatado como ... . O formato pode conter seqüências especiais como \t , \n . Printf não não termina a saída por nova linha. Se apenas um argumento é dado, normalmente é impresso como está.

Se for um número, a formatação padrão será " %.6g ":

CODE  : printf 1.123456789
RESULT: 1.12346

Se, e. $1 é 1.123456789 é normalmente tratado como texto, como em:

CODE  : printf $1
RESULT: 1.123456789
CODE  : printf $1+0 # Force conversion to number
RESULT: 1.12346

Quando você dá mais de um argumento, o primeiro é usado como formato e o restante como parâmetros. Se a alguns parâmetros são fornecidos para preencher o padrão, o comportamento é indefinido .

printf "%d %s\n", 123, "hello"
         || | |    |      |
         || | |    |      +----- Parameter 2
         || | |    +------------ Parameter 1
         || | +----------------- Print new-line
         || +------------------- Print parameter 2 as string
         |+--------------------- Print literal space
         +---------------------- Print parameter 1 as digit

printf "%d %s\n", 123, "hello"
# Gives: 123 hello
printf "%d %s\n", "hello", 123
# Gives: 0 123
printf "%d %s\n", 123
# Gives undefined result (according to format one parameter is missing)

E se os argumentos forem dados sem qualquer espaço reservado, eles serão descartados:

printf "%d", 123
# Gives: 123
printf "%d", 123, 22
# Gives: 123
printf "%d", 123, 22, "\t", "foo", 5566, 12.55, "\n", "blah"
# Gives: 123

O caractere % indica "aqui está uma especificação de conversão" . Se uma especificação não válida é fornecida, como em uma que não é definida por awk , o comportamento é não especificado . Outro texto é tratado como texto normal.

printf "Hello %w", "what"
# Usually: Hello %w
# But no guarantee

printf "ABC", "DEF", "GHI"
# Result: ABC

No seu código, você freqüentemente usa a entrada do arquivo como formato para printf. Se esses campos não forem printf , serão impressos como texto normal. Os parâmetros são descartados.

# Example, say:
#     $4 = "%d %s\n"
#     $8 = "33.2"
#     $9 = "good"
printf $4, $8, $9
#
# Result: 33 good

# Say:
#     $4 = "14"
#     $8 = "33.2"
#     $9 = "good"
printf $4, $8, $9
#
# Result: 14
printf $4, "\t", $8, "\t", $9
#
# Result: 14

Seu script formatado:

< pool.sam awk '
# 1.
/./ {                   # IF line not empty THEN
    printf $1           #   print field 1
}                       # ENDIF
# 2.
{
    printf $7 + 1, "\t" # printf with format = $7 + 1 and parameter <tab>
}
# 3.
{
    printf $3, "\t"     # printf with format = $3 and parameter <tab>
}
# 4.
{
    # 4.1
    if ($2 != 16) {       # IF field 2 is not 16 THEN
        print "\t", "+";  #    print <tab> + "+" (Terminate with newline)
    } else {              # ELSE
        print "\t", "-";  #    print <tab> + "-" (Terminate with newline)
    }                     # ENDIF

    # 4.2
    {
        printf $4, "\t", length($10) + $4, "\t", "1"
        # printf: pattern="field 4"
        #         parameters=<tab>, length of field 10 + field 4
    }
}
'

Digamos que você tenha:

$ cat pool.sam
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Isso lhe daria (usando numeração no código acima):

1.   printf "1"'                    => '1'
2.   printf 8, "\t"'                => '8'
3.   printf "3", "\t"               => '3'
4.1  print  "\t", "+"               => '<tab>+<new-line>'
4.2  printf "4", "\t", 6, "\t", "1" => '4'

Resultado final:

183    +
4

Uma reescrita que pode levá-lo um pouco a caminho:

awk '
/./ {
    printf "%s%d\t%d\t", $1, $7 + 1, $3

    if ($2 != 16) {
        printf "+"
    } else {
        printf "-"
    }

    printf "%d\t%d\t1\n", $4, length($10) + $4
}
' pool.sam

A declaração if, (em perigo de confundir você), também pode ser escrita de uma só vez como:

printf "%s", $2 != 16 ? "+" : "-"

Leia as strings de formato e printf . O formato de alinhamento é frequentemente muito útil, assim como a formatação de floats, etc.

right_pad=-10
printf "%*s: %5d\n", right_pad, "vix", 23
printf "%*s: %5d\n", right_pad, "popul", 336
printf "%*s: %5.2f\n", right_pad, "vidi", 42.129542488
printf "%5s %-10d +%d\n", "OK", 33, 44

Saída:

vix       :    23
popul     :   336
vidi      : 42.13
   OK 33         +44

Mais fácil, pelo menos eu acho, é usar um script em vez de uma linha de comando ao jogar.

    
por 11.10.2013 / 14:50
3

você está executando muito printf s para esse trabalho. porque não simplesmente fazer algo como

cat pool.sam |\
 awk '/./ {printf $1,$7+1,"\t"$3,"\t",($2!=16)?"+","-",$4,"\t",length($10)+$4,"\t1"}}'
    
por 11.10.2013 / 08:46