awk com instruções if

8

Estou tentando imprimir de um arquivo usando o awk, mas minha saída está vazia. Aqui está o meu código até agora

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts
done < Accounts

Eu também tentei isso:

accountNum=$1
while read -r LINE || [[ -n $LINE ]] ; do
            echo $LINE  | awk -F',' '{ if($1==accountNum) { print $3.$2 } }' 
done < Accounts

O arquivo de entrada é:

1,Doe,John
2,Rooney,Wayne
3,Smith,Will
4,Crow,Russel
5,Cruise,Tom

A saída esperada quando eu executo o arquivo é

$./file.sh 3
Will Smith

Mas recebo o seguinte

$./file.sh 3
$

Isso não é nada está sendo impresso. Eu sei a solução com o corte, mas eu quero usar o awk.

    
por gkmohit 21.07.2014 / 04:48

4 respostas

7

Você deve usar a opção -v de awk :

awk -F',' -v accNum="$1" '$1 == accNum {print $3,$2}'

Com $1 nas aspas duplas, o shell manipulará todo o seu caractere especial (se tiver) para você.

    
por 21.07.2014 / 07:26
3

Você tem:

accountNum=$1
awk -F',' '{ if($1==accountNum) { print $3.$2 } }' Accounts

Como a variável accountNum da shell entra em awk ? Não precisa: você precisa fornecer seu valor para awk explicitamente. Você pode usar:

awk -F',' '{ if($1=='"$accountNum"') { print $3.$2 } }' Accounts

que deixa aspas simples e faz com que o shell substitua o valor de sua variável no comando awk e, em seguida, reentra aspas simples para o restante da cadeia de caracteres de comando.

Um script melhor ou pelo menos mais idiomático seria:

#!/bin/sh
accountNum=$1
awk -F, '$1 == "'"$accountNum"'" { print $3,$2 }' Accounts

que lida com números de contas não numéricos (citando a variável substituída), usa um bloco de padrões em vez de um if explícito (o bloco {} será executado se o teste for verdadeiro) e imprime um espaço entre os nomes como você queria (por causa de , ). Se você preferir usar if explicitamente, mova o teste para dentro da instrução if existente.

Dependendo da sua meta real, awk pode não ser o melhor ajuste para o que você está fazendo. O acima ainda falhará se o $1 do script tiver aspas nele. O loop de shell que você tinha não estava fazendo nada útil, embora tenha repetido a saída várias vezes.

    
por 21.07.2014 / 05:04
3

Seu script já praticamente faz o trabalho sem awk :

while IFS=, read -r num last first
    do  [ $((num==accountNum)) -eq 1 ] && 
        printf '%s.%s\n' "$first" "$last"
done < Accounts

Não estou sugerindo que essa seja uma solução melhor ou mais eficiente do que usar awk sozinho, mas se você quiser o while...read loop, isso certamente superará os processos awk separados por cada linha. Apenas um FYI, eu acho.

    
por 21.07.2014 / 06:42
1
#!/bin/bash

awk -v a="$1" -F ',' '$1 == a { print $3, $2 }' Accounts

Com -v a="$1" , definimos a awk variable a como o valor do primeiro argumento de linha de comando do script e, em seguida, especificamos que a entrada é separada por vírgula com -F ',' . Se a primeira coluna for igual ao valor de a , imprima as outras duas colunas na ordem inversa.

Você não recebe nada em sua saída enquanto está comparando a primeira coluna com a awk variable accountNum , que não está definida.

Se houvesse uma entrada cuja primeira coluna tivesse 0 (zero), essa entrada teria sido impressa. Isso ocorre porque o valor de variáveis não definidas em awk é avaliado como zero.

    
por 16.02.2017 / 15:54