特定の割合の行に特定の文字列が含まれている場合にファイルを移動するためのシェルスクリプト

特定の割合の行に特定の文字列が含まれている場合にファイルを移動するためのシェルスクリプト

特定の割合の行に特定の文字列が含まれている場合は、ファイルを移動するシェルスクリプトを作成しています。

私のディレクトリには約2000個のファイルがあり、各ファイルにはデータ列が含まれています。各ファイルの行数は異なります。最初の行はタイトルで、他の行には0より大きい数字が含まれ、小数点以下6桁まで正確です。前任者:

OMEGA
0.000010
0.000010
0.042214
0.042214
0.042214
0.042214
1.147412

行の10%以上が1より大きい値を含むすべてのファイルに興味があります。 「1」を含む行の割合を使用します。 "."に - しかし、構文に問題があります。 ".omega"は私が興味のあるファイルの拡張子です。

これが私が持っているものです:

for file in *.omega
do
 if [ $(($(grep '1.' $file | wc -l) / $(grep '.' $file | wc -l)) * 100) -ge 10 ]; then
 mv $file positive_COGs/ 
 fi
done

私は成功せずにブラケット/ブラケットを配置しようとしました。また、 - "-ge"を使用して%(整数ではない)を整数 "10"(?)と比較するのが適切かどうかはわかりません。

どんなアドバイスも本当にありがとうございます。 bashを使ってスクリプトを実行しています。

乾杯!

答え1

問題は、bashが整数演算を実行するので、20/50を取ると常に0であることです。したがって、テスト数> 1を行数で割った値は0、0 * 100は0、常に10未満です。

除算する前に100を掛けると、希望の結果が出ると思います。

答え2

最新バージョンのGNU 4.xでは、awk次のことができます。

awk '
  BEGINFILE { count = 0 }
  FNR == 1  { next }
  $1 > 1.0  { count++ }
  ENDFILE   { if (count/(FNR-1) >= 0.1) printf "mv %s positive_COGs\n", FILENAME }
' *.omega | sh

カウンタを初期化し(BEGINFILE)、ヘッダー行をスキップし(FNR == 1)、データファイルで見つかった数字に基づいて計算し、ENDFILE条件に一致するファイル(またはシェルコマンド)を印刷します()。次に、mvシェルにコマンドを入力して移動を実行します。

答え3

/整数除算は算術式で行われます。つまり、商演算子です。ほとんどのシェルは浮動小数点演算ではなく整数演算のみを実行できます。

合計で除算し、100 を乗算する代わりにその逆を実行します。これによりgrep … | wc -l単純化されますgrep -c

その上、は間違っていました。grep '1.'a 次の文字が続くすべての行を選択します。つまり、行の末尾ではなくaを含む行を選択します。 10の間の番号付きの行を選択してください。11K+1と10K+ 2の場合を使用しますgrep '1\.'。 1より大きい数字を含む行を選択するには、を使用しますgrep '[1-9][0-9]*\.'

空でgrep .ない行が選択されます。すべての行を選択するには、を使用しますwc -l。数字のある行のみを選択するには、次のように使用しますgrep '[0-9]'(ここには数字のみの行だけでなく、どこにでも数字を含む行が含まれます)。

if [ $(($(grep -c '[1-9][0-9]\.' <"$file") * 100 / $(grep -c '[0-9]' <"$file"))) -ge 10 ]; then

ファイルを一度だけ処理し、発生する数値を計算する方が高速で強力です。これにはawkを使用できます。

if awk '
    $0 >= 1 {good += 1}
    $0 != 0 || $0 ~ /^ *0*\.0*$/ {total += 1}
    END {if (good < total/10) exit(1)}
'; then

関連情報