imbrogliare con if dichiarazioni


8

Sto provando a stampare da un file usando awk, ma il mio output è vuoto. Ecco il mio codice finora

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

Ho anche provato questo:

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

Il file di input è:

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

L'output previsto quando eseguo il file è

$./file.sh 3
Will Smith

Ma ottengo il seguente

$./file.sh 3
$

Non si sta stampando nulla. Conosco la soluzione con cut, ma voglio usare awk.

Risposte:


8

Dovresti usare l' -vopzione di awk:

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

Con $1virgolette doppie, la shell gestirà tutto il suo carattere speciale (se presente) per te.


3

Hai:

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

Come funziona la variabile di shell accountNumentrare awk? Non lo è: è necessario fornire awkesplicitamente il suo valore . Puoi usare:

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

che lascia le virgolette singole e la shell sostituisce il valore della sua variabile nel awkcomando, quindi inserisce nuovamente le virgolette singole per il resto della stringa di comando.

Una sceneggiatura migliore o almeno più idiomatica sarebbe:

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

che si occupa di numeri di conto non numerici (citando la variabile sostituita), utilizza un blocco modello anziché un esplicito if(il {}blocco verrà eseguito se il test prima è vero) e stampa uno spazio tra i nomi come desiderato (a causa di ,). Se si preferisce utilizzare ifesplicitamente, spostare il test all'interno dell'istruzione esistente if.

A seconda del tuo vero obiettivo awkpotrebbe non essere la soluzione migliore per quello che stai facendo. Quanto sopra fallisce ancora se lo script $1contiene delle virgolette. Il loop shell che avevi non stava facendo nulla di utile, sebbene avrebbe ripetuto l'output molte volte.


stai dicendo che dovrei rimuovere il whileloop? :)
gkmohit,

Almeno per gli esempi, non sta facendo nulla per aiutarti.
Michael Homer,

3

Il tuo script già praticamente fa il lavoro senza alcuno awk:

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

Non sto suggerendo che questa sia una soluzione migliore o più efficiente rispetto all'utilizzo awkda solo, ma se vuoi il while...readloop, questo sicuramente batte awkprocessi separati per ogni riga. Solo un FYI, immagino.


Non solo un awk per ogni riga, ma quel awk legge nuovamente l'intero file per ogni riga che la shell stessa legge. Modo per ottenere un algoritmo O (n ^ 2).
Paul_Pedant,

1
#!/bin/bash

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

Con -v a="$1"impostiamo la awkvariabile asul valore del primo argomento della riga di comando dello script, quindi specificiamo che l'input è separato da virgola -F ','. Se la prima colonna è uguale al valore di a, stampare le altre due colonne in ordine inverso.

Non ottieni nulla nel tuo output mentre stai confrontando la prima colonna con la awkvariabile accountNum, che non è impostata.

Se ci fosse stata una voce la cui prima colonna aveva 0 (zero), quella voce sarebbe stata stampata. Questo perché il valore delle variabili non impostate in viene awkvalutato a zero.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.