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ê.
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.
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.
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.
#!/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.