我尝试编写一个Bash脚本,该脚本读取包含多列数据的文件,并将第二列中的每个值乘以第三列中的每个值,并将所有这些乘法的结果相加。
例如,如果文件看起来像这样:
Column 1 Column 2 Column 3 Column 4
genome 1 30 500
genome 2 27 500
genome 3 83 500
...
脚本应该乘以1 * 30得到30,然后2 * 27给予54(并将其加到30),然后3 * 83得到249(并将其加到84)等。
我一直在尝试使用awk来解析输入文件但不确定如何让操作逐行进行。现在它在读取第一行并且执行对变量的操作后停止。
这是我到目前为止所写的内容:
for file in fileone filetwo
do
set -- $(awk '/genome/ {print $2,$3}' $file.hist)
var1=$1
var2=$2
var3=$((var1*var2))
total=$((total+var3))
echo var1 \= $var1
echo var2 \= $var2
echo var3 \= $var3
echo total \= $total
done
我尝试放置"同时阅读"环绕一切,但无法获得每行更新的变量。我想我的方式错了!
我对Linux和Bash脚本非常陌生,所以非常感谢任何帮助!
答案 0 :(得分:2)
那是因为awk读取整个文件并在每一行上运行它的程序。因此,您从awk '/genome/ {print $2,$3}' $file.hist
获得的输出看起来像
1 30
2 27
3 83
等等,这意味着在bash脚本中,set
命令进行以下变量赋值:
$1 = 1
$2 = 30
$3 = 2
$4 = 27
$5 = 3
$6 = 83
等。但是你只在脚本中使用$1
和$2
,这意味着文件内容的其余部分 - 第一行之后的所有内容 - 都将被丢弃。
老实说,除非你这样做只是为了学习如何使用bash,我会说只是用awk来做。由于awk会自动遍历文件中的每一行,因此很容易将第2列和第3列相乘并保持运行总计。
awk '{ total += $2 * $3 } ENDFILE { print total; total = 0 }' fileone filetwo
这里ENDFILE
是一个特殊的地址,意思是“在每个文件的末尾运行下一个块,而不是在每一行。”
如果你 这样做是出于教育目的,请允许我这样说:你唯一需要知道的关于在bash中进行算术的事情就是你不应该在bash中做算术:-P严重的当你想操纵数字时,bash是适用于该工作的最少适应性很强的工具之一。但是如果你真的想知道,我可以编辑它以包含一些关于你如何主要在bash中完成这项任务的信息。
答案 1 :(得分:0)
我同意awk
通常更适合这类工作,但如果您好奇纯粹的bash
实现会是什么样的:
for f in file1 file2; do
total=0
while read -r _ x y _; do
((total += x * y))
done < "$f"
echo "$total"
done