我正在编写一个 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 之间的行1
1
k+ 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