しかし、動作しません!

しかし、動作しません!

以下のリストに示すように、何千もの行があります。
ファイル名="テキストファイル"

3 2 3 1 4 7
5 8 6 8 9 8
8 9 4 7 3 9 
2 3 4 4 9 2 
2 2 0 9 4 0 
0 9 8 2 4 0

条件を使用して特定の要素(5番目の列など)を検索する必要があります。 (実際には最大値を見つける必要があります。)この出力が必要です。 5番目の列の最大値= 9

ライン:5 8 6 8 9 8

    2 3 4 4 9 2

次のコードを使用しました。

var=$(cat newfifth1 | awk 'BEGIN {max = 0} {if ($5>max) max = $5} END {print max}')
cat textfile | grep "$var" | cat $1 $2 $3 $4 $5 $6 >> newtextfile

しかし、動作しません!

可能であれば、配列を使用するより簡単な方法と方法を教えてください。

答え1

あなたの質問のデータサンプルによると、これはあなたが望むようです(そうでない場合は質問を明確にしてください)。

awk '$5 > max { max = $5 ; out = $0 } END { print out }' datafile

これにより、列5に最大値を持つデータファイルの行が印刷されます。

プログラムは次のように動作します。各行について、5番目の列要素を保存された最大max値(初期0)と比較し、より大きい値が見つかった場合は、割り当てられmaxた値を取得し(以降の比較のため)、現在のRow($0)変数に格納されている最大値を含めますout。プログラムの最後のジョブとして、変数の値がout印刷されます。

データにゼロより小さい値しかない場合(max暗黙のゼロ初期化のため)、わずかな拡張が必要です。通常、maxその値より低いことが知られている値で変数を明示的に初期化するだけで十分です。たとえば、BEGIN { max = -999999 }次の一般的なコードパターンを使用することもできます。

awk '(max==0 && max=="") || $5 > max { max = $5 ; out = $0 } END { print out }' datafile

(max==0 && max=="")条件部分を「maxまだ定義されていませんか」(つまり、まだ値が割り当てられていません)と解釈します。

答え2

これにはいくつかの解決策があります。

2回(無限グループ):

awk '
    {
        if (NR == FNR) {
                if ($5 > max) max = $5
        } else {
                if ($5 == max) print
        }
    }' textfile textfile
  • NRすべての入力で計算されたレコード番号(行番号)。  FNR行番号です現在のファイル内で。したがって、たとえば、3行の長さと4行の長さの awk2つのファイルの入力を使用して実行する場合は、次の値が使用されます。fileCfileDNRFNR

    NR    FNR
     1     1
     2     2
     3     3
     4     1
     5     2
     6     3
     7     4
    

    したがって、テストは、NR == FNR最初のファイルが表示されることを確認する古典的な方法です。 

  • したがって、上記は入力ファイルを2回読みます(最後に2回指定された行を見ましたかtextfile?)。最初のパスで最大値が見つかると、2番目のパスはその値を含むすべての行を印刷します。

ワンショット(アレイを使用):

awk '
    {
        if ($5 >= max) {
                if ($5 > max) {
                        max = $5
                        delete result
                        count = 0
                }
                result[++count] = $0
        }
    }
END { for (i = 0; i <= count; i++) print result[i] }' textfile
  • これにより、最大値と一致する行がという配列に保存されますresult。ファイルの読み取りが完了するまで(ファイルを一度だけ読み取るため)、最大値がわからないため、これは面倒です。したがって、以前に見た値よりも高い値(つまり、新しい最大値を探す場合)に会うたびに、配列を消去して(delete)再開します。result
  • 次に、ファイルの終わりに達すると、見つかった内容を印刷します。

注:5番目の列のすべての値が0以下の場合、上記のコマンドは失敗します。この状況を処理するには、「すべて」(テストを含む)if ($5 >… に変更してください。if (max == "" || $5 >…if ($5 >= max)

関連情報