使用awk和变量操作

时间:2013-03-15 21:12:44

标签: bash scripting awk

我尝试编写一个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脚本非常陌生,所以非常感谢任何帮助!

2 个答案:

答案 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