基于行中操作码(指令)的 ADD 或 SUB 编号

基于行中操作码(指令)的 ADD 或 SUB 编号

如何编写一个awk可以根据输入文件中的行所要求的内容进行添加或减去的脚本?我弄清楚了如何仅进行加法或减法,但不是在一个脚本中进行任一/或。

例如,我想要这个输入:

ADD 5,10,20
SUB 30,5,20

产生这个输出:

35
-55

这是我到目前为止所写的:

#!/bin/awk 
BEGIN {
    FS=","
}

{
    for(i=1;i<=NF;i++) 
        sum+=$i; 
    print sum; sum=0}

但是,显然,它只进行加法,甚至没有获得所有数字。

答案1

一些技巧:

  • 使用空格或逗号作为字段分隔符:FS = "[ ,]"
  • 然后像你一样将数字相加,除了以i = 2
  • 如果第一个字段是SUB,则将总和乘以 -1

答案2

这是实现 Glenn Jackman 算法的一种方法,使用关联数组来保存乘法值(1 或 -1):

$ awk -F ',|[[:blank:]]+' '
    BEGIN {
      mult["ADD"] =  1;
      mult["SUB"] = -1;
    };

    $1 ~ /^(ADD|SUB)$/ {
      sum = 0;
      for (i=2; i <= NF; i++) { sum += $i };
      print sum * mult[$1];
    }' input.txt
35
-55

这也提供了添加其他关键字的框架的开始 - 例如“MULT”或“DIV”或“EXP”(对于这些,您将使用而不是sum=$2启动 for 循环)。i=3i=2

答案3

$ awk -F'[ ,]' '{sum=0; for (i=2; i<=NF; i++) sum+=$i; print ($1=="ADD" ? 1 : -1) * sum}' file
35
-55

如果您必须支持更多操作而不仅仅是 ADD 和 SUB,例如:

$ cat file
ADD 5,10,20
SUB 30,5,20
MULT 2,3,4
DIV 20,2,2

您可以使用 GNU awk 并为您想要支持的每个操作定义函数并间接调用它们:

$ cat tst.awk
function ADD(n)  { sum += n }
function SUB(n)  { sum -= n }
function DIV(n)  { if (n==0) { printf "%s[%d]: Divide by zero error in %s\n", FILENAME, FNR, $0 | "cat>&2"; exit 1 } sum /= n }
function MULT(n) { sum *= n }

BEGIN { FS="[ ,]" }
{
    op = $1
    sum = (op=="SUB" ? -1 : 1) * $2
    for (i=3; i<=NF; i++) {
        @op($i)
    }
    print sum
}

$ awk -f tst.awk file
35
-55
24
5

我必须使用特殊情况的“SUB”才能从您提供的输入中获取您想要的输出,因为它的处理方式与其余的不同(即从零减去的所有数字,而不是所有数字相加/相乘/相除) 。如果 SUB 行上的第一个数字是-30或 ,0那么30所有操作都可以以完全相同的方式处理,例如:

$ cat file
ADD 5,10,20
SUB 0,30,5,20
MULT 2,3,4
DIV 20,2,2

$ cat tst.awk
function ADD(n)  { sum += n }
function SUB(n)  { sum -= n }
function DIV(n)  { if (n==0) { printf "%s[%d]: Divide by zero error in %s\n", FILENAME, FNR, $0 | "cat>&2"; exit 1 } sum /= n }
function MULT(n) { sum *= n }

BEGIN { FS="[ ,]" }
{
    op = $1
    sum = $2
    for (i=3; i<=NF; i++) {
        @op($i)
    }
    print sum
}

$ awk -f tst.awk file
35
-55
24
5

相关内容