リストがあります。
2
2
2
3
2
2
2
4
2
2
2
上と下の3段階の値より少なくとも2倍大きい値を同じ列に印刷したいと思います。
出力は
4
どうすればいいですか?私も同様の質問をしました。ここ、よりよく説明するためにここに書いています。ありがとうございます。
20171006更新:実際の入力ファイルを過度に単純化して申し訳ありません。実際にはリストではなくテーブルです。複数の列(列2、3、4など)から選択し、列1を印刷する必要があります。その列に対してこのようなスクリプトの情報をどのようにマージしますか?
A 2 2 2
B 2 2 2
C 2 2 2
D 3 3 3
E 2 2 2
F 2 2 2
G 2 2 2
H 4 4 4
I 2 2 2
J 2 2 2
K 2 2 2
そして得る
H
答え1
でこれを行うことができますawk
。 3行目と最後の行を6行目と現在の行とを比較するには、最初の6行を保存する必要があります。これの一般的なトリックは、保持したい行数にインデックス付きの配列であるNR%6
リングバッファを使用することです6
。
awk '
NR > 6 {
x = saved[NR%6]; y = saved[(NR - 3) % 6]; z = $0
if (y >= 2*x && y >= 2*z) print y
}
{saved[NR % 6] = $0}' < file
編集するには:比較するキーと値を保存します。
awk -v key=1 -v value=2 '
NR > 6 {
x = saved_value[NR%6]; y = saved_value[(NR - 3) % 6]; z = $value
if (y >= 2*x && y >= 2*z) print saved_key[(NR - 3) % 6]
}
{saved_key[NR % 6] = $key; saved_value[NR % 6] = $value}' < file
どこkey
に印刷する列のインデックスとvalue
比較する値を含む列があります。
または、2、3、4列(平均など)に基づいて目的の指標を選択します。
awk '
{metric = ($2 + $3 + $4) / 3}
NR > 6 {
x = saved_metric[NR%6]; y = saved_metric[(NR - 3) % 6]; z = $metric
if (y >= 2*x && y >= 2*z) print saved_key[(NR - 3) % 6]
}
{saved_key[NR % 6] = $key; saved_metric[NR % 6] = $metric}' < file
答え2
メモリ内のファイル全体を読み取らずに:
paste <(tail -n+4 file.txt | head -n-3) <(head -n-6 file.txt) <(tail -n+7 file.txt) |
awk '$1 >= 2*$2 && $1 >= 2*$3 {print $1}'
<(...)
これには、構成(AT&Tksh
またはbash
)を処理できるシェルと負のzsh
オフセットhead
をサポートする実装が必要です。
説明する:上記のコマンドは、paste
現在の値、ステップ3の上の値、およびステップ3の下の値を同じ行に入れて、2倍awk
以上の条件を確認します。
答え3
アッ解決策:
awk 'function mean(sum){
m=sum/3; return (int(m) == m)? m: int(m)+1
}
{ a[NR]=$0 }
END{
for(i=4;i<=NR-3;i++)
if (a[i]>=mean(a[i-3]+a[i-2]+a[i-1])*2 &&
a[i]>=mean(a[i+3]+a[i+2]+a[i+1])*2)
print a[i]
}' file
a[NR]=$0
- すべての値をa
レコード番号で索引付けされた配列として収集NR
出力:
4
答え4
したがって、これを行うには、3 + 1 + 3入力行のスライドウィンドウを維持する必要があります。
awk -vn=3 -va=2 'BEGIN { N=2*n+1 } { t=(NR-n)%N; m=NR%N; b=(NR+n)%N; w[b]=$0 } NR >= N && w[m] >= a*w[t] && w[m] >= a*w[b] { print w[m] }' file
n
これにより、条件を満たすすべての値が印刷され、コマンドラインで変数を調整(変更)して距離を簡単に変更でき、重みを変更-vn=3
(変更)して距離を簡単に変更できるという利点があります。a
-va=2
このコードは最後のN値を循環バッファに格納します。ここで、Nは2 * n + 1ですw
。中間値がバッファの最初の値(「top」の場合)の倍数と、バッファの最後の値(「bottom」の場合)の倍数より大きい場合、w[m]
それを印刷します。a
w[t]
t
a
w[b]
b
公開スクリプトawk
:
BEGIN { N = 2*n + 1 }
{
t = (NR - n)%N
m = NR%N
b = (NR + n)%N
w[b] = $0
}
NR >= N && w[m] >= a*w[t] && w[m] >= a*w[b] { print w[m] }