如果一定百分比的行包含特定字符串,则用于移动文件的 Shell 脚本

如果一定百分比的行包含特定字符串,则用于移动文件的 Shell 脚本

我正在编写一个 shell 脚本,如果一定百分比的行包含特定字符串,则可以移动文件。

我的目录中有大约 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) 匹配的文件(或 shell 命令)。然后将命令mv输入到 shell 中以执行移动。

答案3

/算术表达式中执行整数除法,即它是商运算符。大多数 shell 只能进行整数运算,不能进行浮点运算。

不要除以总数,然后乘以 100,而是执行相反的操作。当你这样做时,grep … | wc -l可以简化为grep -c.

此外,是错误的:它选择包含 a后跟另一个字符的grep '1.'所有行,即包含 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

相关内容