2013-03-15 34 views
1

我试图写一个bash脚本,有几个数据列读取文件,并在乘以通过第三列的每个值的第二列中的每个值,将所有的乘法结果一起。对变量用awk与运营

例如,如果该文件是这样的:

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

这是因为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中执行此任务的信息。

+0

感谢您的解释!这实际上是一个更大的bash脚本的一小部分,所以我试图把所有的东西都放在一起,只是为了简单。 – Joltex 2013-03-15 22:00:37

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 
+0

酷!谢谢。 – Joltex 2013-03-15 22:01:12