web-dev-qa-db-fra.com

Awk avec des déclarations si

J'essaie d'imprimer à partir d'un fichier en utilisant AWK, mais ma sortie est vide. Voici mon code jusqu'à présent

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

J'ai aussi essayé ceci:

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

Le fichier d'entrée est:

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

La sortie attendue lorsque je cours le fichier est

$./file.sh 3
Will Smith

Mais je reçois ce qui suit

$./file.sh 3
$

C'est rien n'est imprimé. Je connais la solution avec la coupe, mais je veux utiliser awk.

8
gkmohit

Tu devrais utiliser -v Option de awk:

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

Avec $1 Dans double citation, la coquille gérera tout son caractère spécial (si elle a) pour vous.

8
cuonglm

Tu as:

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

Comment la variable de coquille accountNum entrera-t-elle dans awk? Ce n'est pas le cas: vous devez fournir sa valeur à awk explicitement. Vous pouvez utiliser:

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

qui laisse des guillemets simples et que la coque substitue la valeur de sa variable dans la commande awk, puis réentre des guillemets simples pour le reste de la chaîne de commande.

Un script meilleur ou au moins plus d'idiomatique serait:

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

qui traite avec des numéros de compte non numériques (citant la variable substituée), utilise un bloc de motif au lieu d'un if ({} Block s'exécutera si le test avant qu'il soit vrai) et imprime un espace entre les noms que vous le souhaitez (à cause de ,). Si vous préférez utiliser if _ explicitement, déplacez le test dans votre relevé existant if.

Selon votre objectif réel awk peut ne pas être le meilleur ajustement pour ce que vous faites. Ce qui précède échoue si le script $1 a des citations dedans. La boucle de coquille que vous n'aviez rien fait d'utile, même si cela aurait répété la production plusieurs fois.

3
Michael Homer

Votre script fait déjà pratiquement le travail sans aucun awk du tout:

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

Je ne suggère pas que c'est une solution meilleure ou plus efficace que d'utiliser awk seul, mais si vous voulez le while...read boucle, cela bat certainement des processus séparés awk par chaque ligne. Juste un fyi, je suppose.

3
mikeserv