web-dev-qa-db-ja.com

配列値を出力しないawkで分割

次の内容の文字列tstArr2があります

'3 5 8'

今awkでフラットファイルを解析したい

test my array which array is better array

INDIA USA SA NZ AUS ARG GER BRA
US AUS INDIA ENG NZ SRI PAK WI BAN NED IRE

これらの番号付きの列でのみ。私は以下を試しました

awk -vA="$tstArr2" 'BEGIN{split(A,B," ");} {if(NR>1){for(i=1; i<= length(B); i++){printf "%s ",B[i]}}print " "}' testUnix3.txt

しかし、それは言います

awk: Cannot read the value of  B. It is an array name.

The input line number is 2. The file is testUnix3.txt.
The source line number is 1.

何が足りないのですか?次のことを試してみると

awk -vA="$tstArr2" 'BEGIN{split(A,B," ");} {if(NR>1){for(i in B){printf "%s ",$B[i]}}print " "}' testUnix3.txt

出力を出力しますが、順序が正しくありません。私はそれらを整然とさせたい。説明してください。必要な出力:

 SA AUS BRA

 INDIA NZ WI
3
recmach

POSIX定義 length in awkは文字列関数であり、引数は文字列と見なされます。配列を引数としてlengthを使用することは、不特定の動作です。

gawk(バージョン> = 3.1.6)OS XバージョンのAWK のようなawkの一部の実装では、lengthを使用できます。配列を引数として使用すると、配列内の要素の数が返されます。

awkの配列は連想配列であり、連想配列をループすることは順序について何も保証しません。この場合、 split 関数を利用できます。この関数は、フィールドの数を返し、配列の要素の数を取得します。

おそらく、あなたは試すことができます:

$ awk -vA="$tstArr2" '
  BEGIN{n = split(A,B," ");}
  {
    if(NR > 1) {
      for(i = 1;i <= n;i++) {
        printf "%s ",$B[i];
      }
    }
    print " ";
  }
' file

SA AUS BRA  
INDIA NZ WI
5
cuonglm

(GNU以外のawkについては、@ cuonglmの回答を参照してください。)

これをテストファイルとして:

_$ cat testUnix3.txt 
test my array which array is better array

INDIA USA SA NZ AUS ARG GER BRA
US AUS INDIA ENG NZ SRI PAK WI BAN NED IRE
_

このコードは、列3、5、および8を選択します。

_$ tstArr2='3 5 8'
$ awk  -vA="$tstArr2" 'BEGIN{split(A,B," ");} NR>1{for(i=1; i<= length(B); i++) printf "%s ",$B[i]; print "";}' testUnix3.txt

SA AUS BRA 
INDIA NZ WI 
_

上記はGNU awkでテストされました。

awkループと順序

awkには連想配列があります。 Grymoire awkチュートリアル が説明するように:

特に連想配列を使用する場合、連想配列には1つの小さな問題があります。 for 各要素を出力するコマンド:出力の順序を制御することはできません。

これが、for(i in B)ループを使用する、引用した他のコードが列を順不同で出力する場合がある理由です。

GNU awkには、この問題を克服するための拡張機能があります。

_$ gawk -vA="$tstArr2" 'BEGIN{split(A,B," "); PROCINFO["sorted_in"]="@ind_num_asc"} {if(NR>1){for(i in B){printf "%s ",$B[i]}print " "}}' testUnix3.txt

SA AUS BRA  
INDIA NZ WI  
_

_PROCINFO["sorted_in"]="@ind_num_asc"_を設定すると、インデックスは数値の昇順でループされます。このGNU拡張子は文書化されています ここ

2
John1024

このような単純なタスクにawkのような強力な機器を使用するには、多くのオーバーヘッドがあります。

tstArr2='3,5,8'
tail -n+2 testUnix3.txt | cut -d' ' -f"$tstArr2"
1
Costas