2017-02-17 15 views
1

私はファイルa.txtを持っています。 各行には多くの番号がA.TXTにありますawkでマップをクリアする方法は?

1 2 3 1 2 
5 6 7 7 
19 20 20 

私は以下の結果と同様に、重複した番号なし各行を印刷する必要があります。

1 2 3 
5 6 7 
19 20 

私はawkの中でマップを使用する必要がありますが毎回地図をクリアしてください。 各行を読むときにawkのマップをクリアする方法がわかりません。

awk '{ split($0, arr, " "); \ 
for(i=1;i<=length(arr);i++){dup_map[arr[i]]=1;} \ 
for(num in dup_map){printf("%s ", num);} printf("\n"); clear dup_map; } \ 
}' a.txt 

誰かがawkでマップをクリアする方法を教えてもらえますか?

答えて

2

gawkがこの機能delete有する:これは

split("", array) 

分割機能によって達成することができるAWKで

delete array 

(セクションを参照の組込み関数の文字列 操作用)ターゲット配列を最初にクリアします。このコールでは、 にヌル文字列を分割するように求められます。分割するデータがないため、 関数は単純に配列を消去してからリターンします。

(私はgawk manual on www.chemie.fu-berlin.deでこれを見つけました。)

+0

はい、ありがとうございます!削除dup_mapは良いです! –

+0

'delete(配列)'がPOSIXの一部となったため、配列を初期化する 'split(" "、array)'は何年も必要とされていませんでした。あなたが使用しているawkのバージョンがそれを必要とするならば、それはおそらく他の多くの機能がないので、より現行のawkバージョン(好ましくはgawk)を入手する必要があります。 –

+0

@エドモートン私は高齢です。それで、私は古いものが好きな理由です... – Scheff

0
awk '{split("",M);for(i=1;i<=NF;i++)if($i in M)$i="";else M[$i]++;$0=$0}7' YourFile 

注:awkはすでにあなたのためのフィールドを分割するので、あなたは、最初の分割を必要としない

awk '# for non empty lines 
    /./ { 
     # reset array Map 
     split("", Map) 
     # for each field (separtor is space) 
     for(i=1; i<=NF ;i++) { 
     # if the field content is in map, set it to empty string 
     # if not, add it to the map 
     if($i in Map) $i="" 
      else Map[ $i]++ 
     } 
     # rewrite the line for single separator (not mandatory) 
     $0=$0 
     } 
    # print the resulting line (default action) 
    7 { print } 
    ' YourFile 
+0

'split(" "、array) '' delete(配列) 'がPOSIXの一部になって以来、配列を初期化することは何年も要求されていませんでした。あなたが使用しているawkのバージョンがそれを必要とするならば、それはおそらく他の多くの機能がないので、より現行のawkバージョン(好ましくはgawk)を入手する必要があります。 –

+0

私のAIXに: '>>>削除(<<< awk:0602-502私のLinux(gawk)上で文が正しく解析できない、問題ありません – NeronLeVelu

+0

それから、それはPOSIXではないので、 REの間隔は?キャラクタークラス?その他? –

0

ノート、

$ awk '{delete a; 
     for(i=1;i<=NF;i++) a[$i]; 
     for(k in a) printf "%s ", k; 
     print ""}' file 

1 2 3 
5 6 7 
19 20 

または、dエントリをeletingの代わりに、配列

$ awk '{for(i=1;i<=NF;i++) a[$i]; 
     for(k in a) 
      {printf "%s ", k; delete a[k]} 
     print ""}' file 
0

これは、あなたが欲しいものを行うには正しい方法です:

$ awk '{ 
    delete(seen) 
    for (i=1; i<=NF; i++) { 
     if (!seen[$i]++) { 
      printf "%s%s", (i>1 ? OFS : ""), $i 
     } 
    } 
    print "" 
}' file 
1 2 3 
5 6 7 
19 20 

$i値が見られているのを追跡するseenという名前の配列の慣用的な使用フィールドは、発生した順に印刷されます(in演算子を使用して順序をランダム化する別の回答があります)。また、各行の末尾に空白の文字が印刷されません。それもそうする)。