- ベストアンサー
awk外で宣言した変数の参照
kshを使用して、以下のようなシェルを作成しています。 しかしawk内で$iと$iiが参照出来てない様子です。 どのようにすれば参照できますでしょうか。 ■シェルの中身 #/usr/bin/ksh for i in `cat /tmp/hoge |awk -F : '{ print $3 }' | sort | uniq -d` do if [ $i != "" ]; then for ii in `cat /tmp/hoge` do echo $ii |awk -F ":" '{ if ( $3 -eq $i ) print $ii }' done fi done ■エラー awk: 0602-562 フィールド $() が正しくありません。 入力の行番号は 1 です。 ソースの行番号は 1 です。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
まず、awkの添削から。 '{ if ( $3 -eq $i ) print $ii }' ・-eq に 「等しい」という意味はありません。「等しい」という比較演算子は== です。-eq は「 変数eqを引く」という意味になります。 ・$i,$iiは「i番目/ii番目のフィールド」という意味になります。変数の値を使う場合に$は必要ありません。 さて、この場合のi,iiはkshの変数なので、そのままawkから参照することはできません。 方法としては、次のものが一般的でしょうか。 (1)kshの変数置換機能を使って、awkのスクリプトに埋め込む (2)-vオプションでawkの変数に代入する (1)の方法ではこんな感じ echo $ii |awk -F ":" "{ if ( \$3 == $i ) print \"${ii}\" }" 注意点は ・kshで$を展開したいので、シングルクォートではなくダブルクォートを使用する。 ・$3の$は展開したくないので、\を付ける ・出力は変数iiの文字列なので、awkの文としてダブルクォートでくくった状態にする。ダブルクォートの中にダブルクォートを書くために\を付ける。 (2)の方法ではこんな感じ echo $ii |awk -v a=$i -v b=$ii -F ":" '{ if ( $3 == a ) print b }' ・「-v awkの変数名=値」でawkの変数にあらかじめ値を代入できる。 ・説明のためにawkの変数名をa,bにしたが、別にkshの変数名とそろえてもいい。ただ、kshのi,iiと、awkのi,iiは独立したものだという点は注意しておく。 echo $ii |awk -v i=$i -v ii=$ii -F ":" '{ if ( $3 == i ) print ii }' 応用。 さて、これはifの条件にあったも行をそのまま表示するだけのようですが、入力行は$0になりますので、わざわざiiをawkに渡すことなく echo $ii |awk -v i=$i -F ":" '{ if ( $3 == i ) print $0 }' と書けます。 awkのスクリプトはifを使わなくても 条件 {条件が成り立ったときのアクション} と書けますので echo $ii |awk -v i=$i -F ":" '($3 == i) { print $0 }' と書けます。 さらに、アクションのデフォルトは print $0 なので echo $ii |awk -v i=$i -F ":" '($3 == i)' と書けます。 さて、このスクリプト、同じファイルを何度も読み出して非効率的ですよね。 ちょっとがんばれば、awkだけを使って1回の読み出しで済むようなものも作れます。 挑戦してみてください。
その他の回答 (1)
- graycat000
- ベストアンサー率51% (53/102)
awk内部の変数値を外部から設定したい場合は, awk -v var=xx '{}' とします.たぶん,該当のawkを次のようにすればよいでしょう. echo $ii | awk -v a=$i -v b=$ii -F ":" '{ if ( $3 -eq a ) print b }'
お礼
色々な説明を頂きありがとうございます。 参考にさせて頂きうまく動くようになりました。