【问题标题】:Using awk with Operations on Variables使用 awk 对变量进行操作
【发布时间】:2013-03-16 05:36:35
【问题描述】:

我正在尝试编写一个 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

我尝试在所有内容周围放置一个“while read”循环,但无法让变量随每一行更新。我想我做错了!

我对 Linux 和 Bash 脚本非常陌生,因此非常感谢任何帮助!

【问题讨论】:

    标签: bash scripting awk


    【解决方案1】:

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

    【讨论】:

    • 感谢您的解释!它实际上是一个较大的 bash 脚本的一小部分,所以为了简单起见,我试图将所有内容放在一起。
    【解决方案2】:

    我同意 awk 通常更适合此类工作,但如果您好奇纯 bash 实现会是什么样子:

    for f in file1 file2; do
        total=0
        while read -r _ x y _; do
            ((total += x * y))
        done < "$f"
        echo "$total"
    done
    

    【讨论】:

      猜你喜欢
      • 2011-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多