$ 2 (referência de campo) no awk BEGIN não está funcionando

1

No snippet a seguir, $2 no awk está retornando vazio. O que estou fazendo de errado? Eu estou tentando encontrar a diferença entre MAX e MIN.

#!/bin/ksh
if [ $# -ne 1 ]; then
        echo "Usage: sh 'basename ${0}' filename";
        exit 1;
fi
if [ ! -s ${1} ]; then
        echo "file doesn't exist or is empty";
        exit 1;
fi
sed -e '/^$/d' -e '/^#/d' ${1} |
awk  -F'=' '
        BEGIN {
                MIN=$2; MAX=$2; print MIN;
        }
        {
                if ( $2 > MAX )
                {
                        MAX = $2;
                }
                else if ( $2 < MIN )
                {
                        MIN = $2;
                }
        }
        END {
                DIFF=MAX-MIN; print "DIFF:" DIFF;
        }
'

No entanto, isso está funcionando bem. Por que o $2 não funciona na seção BEGIN ?

#!/bin/ksh
if [ $# -ne 1 ]; then
        echo "Usage: sh 'basename ${0}' filename";
        exit 1;
fi
if [ ! -s ${1} ]; then
        echo "file doesn't exist or is empty";
        exit 1;
fi
sed -e '/^$/d' -e '/^#/d' ${1} |
awk -F'=' '
        {
                if ( MAX == "" || MIN == "" )
                {
                        MAX = MIN = $2;
                }
                else
                {
                        if ( $2 > MAX )
                        {
                                MAX = $2;
                        }
                        else if ( $2 < MIN )
                        {
                                MIN = $2;
                        }
                }
        }
        END {
                DIFF=MAX-MIN; print "DIFF:" DIFF;
        }
'
    
por jw013 10.02.2012 / 22:56

2 respostas

6

BEGIN padrões são executados antes qualquer entrada é lida, portanto, nenhuma das variáveis que se referem a entrada, como NR , campos como $0 ..., serão definidas em qualquer um dos blocos BEGIN . Sua segunda abordagem está correta e muito melhor.¹ A partir da especificação awik POSIX ( ênfase mine):

The awk utility shall recognize two special patterns, BEGIN and END. Each BEGIN pattern shall be matched once and its associated action executed before the first record of input is read ...

¹ Apenas uma observação, também é bom porque não faz suposições sobre o mínimo ou máximo sendo limitado por um valor particular como 0, algo que muitos one-liners que se encontra na internet assumem.

    
por 10.02.2012 / 23:18
1

Se você deseja executar um comando na primeira linha do texto de entrada, use NR==1 pattern, não BEGIN .

awk  -F'=' '
    NR==1 {
            MIN=$2; MAX=$2; print MIN;
    }
    NR>1 {
            if ( $2 > MAX )
            {
                    MAX = $2;
            }
...

Como afirmado por @ jw013, BEGIN pattern é para que as ações sejam executadas antes de você ler a primeira linha.

    
por 11.02.2012 / 15:30