以下のリストに示すように、何千もの行があります。
ファイル名="テキストファイル"
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行の長さのawk
2つのファイルの入力を使用して実行する場合は、次の値が使用されます。fileC
fileD
NR
FNR
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)