awk dengan pernyataan if

8

Saya mencoba untuk mencetak dari file menggunakan awk, tetapi output saya kosong. Ini kode saya sejauh ini

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

Saya juga sudah mencoba ini:

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

File input adalah:

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

Output yang diharapkan ketika saya menjalankan file adalah

$./file.sh 3
Will Smith

Tapi saya mendapatkan yang berikut

$./file.sh 3
$

Itu tidak ada yang sedang dicetak. Saya tahu solusinya dengan cut, tetapi saya ingin menggunakan awk.

gkmohit
sumber

Jawaban:

8

Anda harus menggunakan -vopsi awk:

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

Dengan $1kutipan ganda, shell akan menangani semua karakter spesialnya (jika ada) untuk Anda.

cuonglm
sumber
3

Kamu punya:

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

Bagaimana variabel shell accountNumbisa masuk awk? Tidak: Anda perlu memberikan nilainya awksecara eksplisit. Kamu bisa menggunakan:

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

yang meninggalkan tanda kutip tunggal dan memiliki shell yang menggantikan nilai variabelnya ke dalam awkperintah, kemudian memasukkan kembali tanda kutip tunggal untuk sisa string perintah.

Skrip idiomatik yang lebih baik atau setidaknya akan menjadi:

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

yang berkaitan dengan nomor akun non-numerik (mengutip variabel yang diganti), menggunakan blok pola alih-alih eksplisit if( {}blok akan berjalan jika tes sebelum itu benar), dan mencetak spasi di antara nama-nama yang Anda inginkan (karena ,). Jika Anda lebih suka menggunakan ifsecara eksplisit, pindahkan tes di dalam ifpernyataan yang ada .

Tergantung pada tujuan Anda yang sebenarnya awkmungkin bukan yang paling cocok untuk apa yang Anda lakukan. Di atas masih gagal jika skrip $1memiliki tanda kutip di dalamnya. Shell loop yang Anda gunakan tidak melakukan sesuatu yang berguna, meskipun itu akan mengulangi output berkali-kali.

Michael Homer
sumber
Anda mengatakan saya harus menghapus whileloop? :)
gkmohit
Setidaknya untuk contoh itu tidak melakukan apa pun untuk membantu Anda.
Michael Homer
3

Script Anda sudah praktis melakukan pekerjaan tanpa awksama sekali:

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

Saya tidak menyarankan bahwa ini adalah solusi yang lebih baik atau lebih efisien daripada menggunakan awksendiri, tetapi jika Anda ingin while...readloop, ini tentu saja mengalahkan awkproses terpisah per setiap baris. Hanya FYI, kurasa.

mikeserv
sumber
Bukan hanya satu awk untuk setiap baris, tetapi awk itu membaca seluruh file lagi untuk setiap baris yang dibaca oleh shell itu sendiri. Cara untuk mendapatkan algoritma O (n ^ 2).
Paul_Pedant
1
#!/bin/bash

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

Dengan -v a="$1"kita mengatur awkvariabel ake nilai argumen baris perintah pertama skrip, maka kita menentukan bahwa input dipisahkan dengan koma -F ','. Jika kolom pertama sama dengan nilai a, cetak dua kolom lainnya dalam urutan terbalik.

Anda tidak mendapatkan apa pun dalam output saat membandingkan kolom pertama dengan awkvariabel accountNum, yang tidak disetel.

Seandainya ada entri yang kolom pertamanya memiliki 0 (nol) di dalamnya, entri itu akan dicetak. Ini karena nilai variabel tidak disetel awkdievaluasi ke nol.

Kusalananda
sumber