Ubuntuシステムには次のデータセットがあります。
37.500 0.0000 0.005605
37.750 0.0000 -0.027858
38.000 0.0000 -0.060678
38.250 0.0000 -0.088557
38.500 0.0000 -0.109210
38.750 0.0000 -0.122482
39.000 0.0000 -0.129770
39.250 0.0000 -0.133190
39.500 0.0000 -0.134538
39.750 0.0000 -0.134015
40.000 0.0000 -0.129660
40.250 0.0000 -0.117858
40.500 0.0000 -0.094709
40.750 0.0000 -0.057622
41.000 0.0000 -0.006853
列1の38から40の間の列3の最大値を見つける必要があります。
これは単なるサンプルデータセットです。
答え1
awk '$1 >= 38 && $1 <= 40 && $3 > max {max = $3; out = $0};
END {print out}' input.txt
注:$ 3には正の値はありません。ここで、38 <= $1 <= 40 です。これが出力が空の行になった理由です。 (なぜですか?max
デフォルトは 0 で、その上に負の値が 1 つもないからです。)
正または負のいずれかで最も高い値が必要な場合は、max
$ 3から可能な最小値より小さい値に初期化してください。例えば-9999
:
$ awk -v max=-9999 '$1 >= 38 && $1 <= 40 && $3 > max {max = $3; out = $0};
END {print out}' input.txt
38.000 0.0000 -0.060678
またはBEGIN
代わりにブロックを使用してください-v
。
$ awk 'BEGIN {max=-9999};
$1 >= 38 && $1 <= 40 && $3 > max {max = $3; out = $0};
END {print out}' input.txt
38.000 0.0000 -0.060678
または、Perlを使用して予期しない値に初期化する代わりに、$ maxが定義されていないかどうかをテストします。
$ perl -lane '
if ($F[0] >= 38 && $F[0] <= 40 && (!defined($max) || $F[2] > $max)) {
$max = $F[2];
$out = $_;
};
END { print $out }' input.txt
38.000 0.0000 -0.060678
答え2
「1つの作業のための1つのツール」というUnixの精神の1つの解決策は、行フィルタリングを使用してからソートをawk
使用することですsort
。
awk '$1>=38 && $1<=40' test.txt | sort -n -k 3 -r | head -n 1
具体的には、3番目の列を使用して反転(最も大きい値から始まる)と行を表示する-n
数値ソートを使用しています。良い点は、最初の3つの値、最小値などに拡張するのが非常に簡単です。-k3
-r
head -n 1
答え3
sort
->sed
ソリューション。
引き続き一致する行をホールドバッファ(/^(3[89]|40\.000)/h
)に入れ、最後にホールド+パターンバッファ($x
)と印刷パターンバッファ($p
)を交換します。
$ sort -rk 3n test.txt |sed -nE '/^(3[89]|40\.000)/h;$x;$p'
38.000 0.0000 -0.060678
$
答え4
使用幸せ(以前のPerl_6)
~$ raku -e 'lines.map(*.words).grep(38 < *.[0] < 40).map(*.[2].Num).max.say;' file
または(拡張バージョン):
~$ raku -e 'my @a = lines>>.words; @a.=grep(38 < *.[0] < 40); @a.map(*.[2].Num).max.say;' file
上記のコードは、-0.088557
指定された基準に基づいて単一(最大)値Column_1を返します。つまり、lines
スペース区切り文字を読み取って中断して、words
38と40の間の列1の値(0インデックス=)を見つけ、grep
列3(0インデックス=)の値の固定値からそれを抽出します。.[0]
max
Num
.[2]
[関心のある読者のための注意:0行を返すようにColumn_1基準を変更すると、上記のコードはmax
私が取得するColumn_3値が-Inf
]であることを示しています。
コメントを読むと、OPが上記の値を含む行全体を返す方法も知りたいと思います。次のコードはこれを行います。
~$ raku -e 'my @a = lines>>.words; @a.=grep(38 < *.[0] < 40); put max(@a, :by(*.[2].Num));' file
38.250 0.0000 -0.088557
最後に、読者はここで得られたColumn_3の値が他の公開された回答と異なることがわかります。これは、Column_1値の要求である場合、使用されたRakuコードが言うように正確にOPを取得するためです。〜サイ38と40(つまり、38より大きく40より小さい)。 Column_3 値を指定する代わりに、上記grep
の文を自由に変更して使用することができます(他の答えと同じ)。<=
<
-0.060678
入力例:
37.500 0.0000 0.005605
37.750 0.0000 -0.027858
38.000 0.0000 -0.060678
38.250 0.0000 -0.088557
38.500 0.0000 -0.109210
38.750 0.0000 -0.122482
39.000 0.0000 -0.129770
39.250 0.0000 -0.133190
39.500 0.0000 -0.134538
39.750 0.0000 -0.134015
40.000 0.0000 -0.129660
40.250 0.0000 -0.117858
40.500 0.0000 -0.094709
40.750 0.0000 -0.057622
41.000 0.0000 -0.006853