次のファイルがありますdf
。
1 4
1 6
1 7
1 10
2 3
2 9
2 10
3 4
4 7
9 10
dfの各行にこれらの値の少なくとも1つが含まれるように、最小値のセットを決定する必要があります。
上記でdf
期待するものはout
次のとおりです。
1
2
4
9
動作するプロセスがありますが、非常に遅いです。このタスクをより速く実行したり、プロセスを並列化したりする方法はありますか?
x=1
while [ $x -gt 0 ]
do
i=$(paste df | tr '\t' '\n' | sort | uniq -c |
sort -r -k1,1 -k2,2n | awk 'NR==1{print $2}')
echo $i >> out
grep -vw $i df > tmpdf
cat tmpdf > df
x=$(paste df | wc -l)
done
答え1
以下は「ラインノイズ」Perlです。
perl -lane '
for $f (@F) {push @{$x{$f}}, $.} # 1.
} END {
use List::Util qw/any first/;
sub sort_by_count_desc {
map { $_->[0] }
sort { $b->[1] <=> $a->[1] || $a->[0] <=> $b->[0] }
map { [$_, scalar(@{$x{$_}})] }
@_
}
@ordered = sort_by_count_desc(keys %x); # 2.
%result = ();
for ($i=1; $i<=$.; $i++) { # 3.
$node = first { any {$_ == $i} @{$x{$_}} } @ordered; # 4.
$result{$node} = 1;
}
print join "\n", sort_by_count_desc(keys %result);
' df
どこ
- ファイルの行を繰り返し、各値をその値が表示される行のリストにマップします。
- シェイプリストのサイズに基づいて、降順にソートされた値のソートされた行を生成します。
- 行番号の範囲とforeach行番号を繰り返します。
- 行番号が表示される最初の値を見つける
この出力
1
2
4
10
答え2
これは「バカ」Linux最適化に使用しbash
ますが、特に移植性がなく、アルゴリズムを改善しません。
f=$(mktemp) ; cp df $f
while [ -s $f ] ; do
tr '\t' '\n' < $f | sort | uniq -c | sort -r -k1,1 -k2,2n |
grep -om1 '\S$' | tee >(grep -vwf - $f | sponge $f)
done
rm $f
メモ:
使用df入力ファイルをスクラッチパッドとして使用することはお勧めできません
mktemp
。代わりにこれを使用してください。出力は次のとおりです。標準出力。必要に応じてに変更します
done
。done > out
これ
sponge
util に名前を付ける必要はありません。tmpdf文書。検索文字列変数の代わりにと
tee
を使用してください。grep -f -
$i
wc -l
あることを確認してください0十分ではありませんtest -s
。