web-dev-qa-db-ja.com

ifステートメントのあるawk

Awkを使用してファイルから印刷しようとしていますが、出力が空です。これが私のコードです

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

私もこれを試しました:

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

入力ファイルは次のとおりです。

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

ファイルを実行したときに予想される出力は

$./file.sh 3
Will Smith

しかし、私は以下を得ます

$./file.sh 3
$

それは何も印刷されていません。カットの解決策は知っていますが、awkを使用したいと思います。

8
gkmohit

awk-vオプションを使用する必要があります:

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

二重引用符で囲まれた$1を使用すると、シェルはすべての特殊文字(ある場合)を処理します。

8
cuonglm

あなたが持っている:

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

シェル変数accountNumはどのようにしてawkに入りますか?そうではありません。その値をawkに明示的に提供する必要があります。以下を使用できます。

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

単一引用符を残し、シェルにその変数の値をawkコマンドに代入させ、残りのコマンド文字列に単一引用符を再入力します。

より良い、または少なくとももっと慣用的なスクリプトは次のようになります:

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

非数値のアカウント番号(置換された変数を引用)を処理し、明示的なif{}ブロックは、その前のテストがtrueの場合に実行され、必要に応じて名前の間にスペースを出力します(,)。 ifを明示的に使用する場合は、既存のifステートメント内にテストを移動します。

あなたの実際の目標によっては、awkはあなたがやっていることに最適ではないかもしれません。スクリプトの$1には引用符が含まれています。あなたが持っていたシェルループは何も有用なことをしていませんでしたが、出力を何度も繰り返していました。

3
Michael Homer

あなたのスクリプトは実際にはawkなしで実際に仕事をしています:

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

これがawkを単独で使用するよりも優れた、またはより効率的なソリューションであるとは示唆していませんが、while...readループ、これは確かに各行ごとに別々のawkプロセスに勝ります。参考までに。

3
mikeserv
#!/bin/bash

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

-v a="$1"を使用して、awk変数aをスクリプトの最初のコマンドライン引数の値に設定し、入力が-F ','で区切られたコンマであることを指定します。最初の列がaの値と等しい場合、他の2つの列を逆の順序で出力します。

最初の列をawk変数accountNumと比較しているため、何も出力されません。

最初の列に0(ゼロ)が含まれるエントリがあった場合、そのエントリは出力されます。これは、awkの未設定変数の値がゼロに評価されるためです。

1
Kusalananda