awk mit if-Anweisungen

8

Ich versuche, mit awk aus einer Datei zu drucken, aber meine Ausgabe ist leer. Hier ist mein Code bis jetzt

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

Ich habe auch Folgendes versucht:

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

Die Eingabedatei lautet:

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

Die erwartete Ausgabe beim Ausführen der Datei ist

$./file.sh 3
Will Smith

Aber ich verstehe folgendes

$./file.sh 3
$

Das ist nichts wird ausgedruckt. Ich kenne die Lösung mit Schnitt, aber ich möchte awk verwenden.

gkmohit
quelle

Antworten:

8

Sie sollten die -vOption verwenden awk:

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

Mit $1in doppelten Anführungszeichen behandelt die Shell alle Sonderzeichen (falls vorhanden) für Sie.

cuonglm
quelle
3

Du hast:

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

Wie kommt die Shell-Variable accountNumins Spiel awk? Dies ist nicht der Fall: Sie müssen den Wert awkexplizit angeben. Sie können verwenden:

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

awkDadurch bleiben einfache Anführungszeichen und die Shell ersetzt den Wert ihrer Variablen durch den Befehl. Anschließend werden einfache Anführungszeichen für den Rest der Befehlszeichenfolge erneut eingegeben.

Ein besseres oder zumindest idiomatischeres Skript wäre:

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

Dies behandelt nicht numerische Kontonummern (unter Angabe der ersetzten Variablen), verwendet einen Musterblock anstelle eines expliziten if(der {}Block wird ausgeführt, wenn der Test zuvor wahr ist) und gibt ein Leerzeichen zwischen den Namen aus, wie Sie es wollten (wegen ,). Wenn Sie es ifexplizit verwenden möchten , verschieben Sie den Test in Ihre vorhandene ifAnweisung.

Abhängig von Ihrem tatsächlichen Ziel awkpasst es möglicherweise nicht zu dem, was Sie tun. Das Obige schlägt immer noch fehl, wenn das Skript $1Anführungszeichen enthält. Die Shell-Schleife, die Sie hatten, hat nichts Nützliches getan, obwohl sie die Ausgabe viele Male wiederholt hätte.

Michael Homer
quelle
Wollen Sie damit sagen, dass ich die whileSchleife entfernen soll ? :)
gkmohit
Zumindest für die Beispiele tut es nichts, um Ihnen zu helfen.
Michael Homer
3

Ihr Skript erledigt den Job praktisch schon ohne awk:

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

Ich behaupte nicht, dass dies eine bessere oder effizientere Lösung ist als die awkalleinige Verwendung , aber wenn Sie die while...readSchleife wollen , schlägt dies sicherlich separate awkProzesse pro Zeile. Nur zu Ihrer Information, denke ich.

mikeserv
quelle
1
#!/bin/bash

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

Wenn -v a="$1"wir die awkVariable aauf den Wert des ersten Befehlszeilenarguments des Skripts setzen, geben wir an, dass die Eingabe durch Kommas getrennt ist -F ','. Wenn die erste Spalte dem Wert von entspricht a, drucken Sie die beiden anderen Spalten in umgekehrter Reihenfolge.

Sie erhalten nichts in Ihrer Ausgabe, wenn Sie die erste Spalte mit der awkVariablen vergleichen accountNum, die nicht festgelegt ist.

Hätte es einen Eintrag gegeben, dessen erste Spalte 0 (Null) enthielt, wäre dieser Eintrag gedruckt worden. Dies liegt daran, dass der Wert von nicht gesetzten Variablen in awkNull ergibt .

Kusalananda
quelle