web-dev-qa-db-ja.com

awkの「not in」配列がawkの「in」配列と同じように機能するのはなぜですか?

次のawkスクリプトは、最初の列に基づいて2つのファイルの差分を設定しようとします。

BEGIN{
    OFS=FS="\t"
    file = ARGV[1]
    while (getline < file)
        Contained[$1] = $1
    delete ARGV[1]
    }
$1 not in Contained{
    print $0
}

これがTestFileAです。

cat
dog
frog

これがTestFileBです。

ee
cat
dog
frog

ただし、次のコマンドを実行すると、

gawk -f Diff.awk TestFileA TestFileB

スクリプトに "in"が含まれているかのように出力を取得します。

cat
dog
frog

「not in」が私の意図にとって正しい構文であるかどうかは不明ですが、「in」を書き込んだときとまったく同じように動作する理由に非常に興味があります。

24
merlin2011

_element not in array_について doc が見つかりません。

!(element in array)を試してください。


awknotを初期化されていない変数と見なすため、notは空の文字列として評価されます。

_$1 not == $1 "" == $1
_
30
kev

私はこれを理解しました。 (x in array)は値を返すため、「not in array」を行うには、次のようにする必要があります。

if ( x in array == 0 )
   print "x is not in the array"

またはあなたの例では:

($1 in Contained == 0){
   print $0
}
19
Jeff

この問題の解決策では、次のif-elseステートメントを使用します。

if($1 in contained);else{print "Here goes your code for \"not in\""}
1
Peter

これがあなたがやろうとしていたようなことかどうかはわかりません。

#! /bin/awk
#は2番目のargファイルを読み取り、1列目にあるトークン
#のハッシュを作成します。次に、最初のargファイルを読み取って、すでに定義されているトークンと一致しない1列目にトークンがある
#行を出力します
 BEGIN {
 OFS = FS = "\ t" 
 file = ARGV [1] 
 while(getline <file)
 Contained [$ 1] = $ 1 
#delete ARGV [1]#わからないここで何を考えていたか
#for(i in Contained){print Contained [i]}#デバッグ、サディストのためだけではありません
 close(ARGV [1])
} 
 {
 if($ 1含む){} else {print $ 1} 
} 
 
1
starbolin

Awkコマンドラインでは、次を使用します。

 ! ($1 in a)
$1 pattern
a array

例:

awk 'NR==FNR{a[$1];next}! ($1 in a) {print $1}' file1 file2
0
Achraf Ktami