在计算发送到 C 文件后使用 AWK 打印列

Using AWK to print a column after calculations sent to a C file

我的文本文件:

0000000022:tom:987:1,2:3,4
0000000223:jody:65:5,6:7,8
0000002224:ellie:43:9,8:7,6
0000022225:paul:21:5,4:3,2
0000222226:greg:0:1,2:3,4

我的终端命令:

$ ./script myFile.txt 2 3 4 5

我的代码:

#!/usr/bin/env bash

file=""

balance=$( awk -F'[:,]' '{ print $(NF-4) }' "$file" )

fee=$( awk -F'[:,]' '{ print $(NF-3), $(NF-2), $(NF-1), $(NF) }' "$file" | ./myProgram     )

我怎样才能从余额中扣除费用,例如balanceAfter=$( balance - fee)

我正在使用 awk 浏览我的文件,然后我将文件中的字段和位置参数发送到 myProgram.c 以计算费用。然后我想打印文件中没有足够钱支付费用的人员的姓名。第三列是他们的余额。如果不清楚,请评论给我澄清。

对于这种情况,费用最终为 28,但会根据不同的参数和字段而改变,但在这种情况下,费用为 28,因此应该导致 Paul 和 Greg 的名字被推送到输出,因为他们资金不足

终端命令后我想要的输出:

$ ./script myFile 2 3 4 5
paul
greg

我的计算费用的.c程序是这样调用的:

$ echo 1 2 3 4 | ./myProgram 1 2 3 4

.c程序

// fee calculator
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char **argv) {
    // verify parameters just in case
    if (argc != 5) {
        return 0;
    }
    char *aStr = argv[1];
    char *bStr = argv[2];
    char *cStr = argv[3];
    char *dStr = argv[4];
    // Converts parameters to integers to use in calculations
    int a = atoi(aStr);
    int b = atoi(bStr);
    int c = atoi(cStr);
    int d = atoi(dStr);
    int u1TapOn, v1TapOn, u2TapOff, v2TapOff;
    int x1, y1, x2, y2;
    int fare;
    char strCoordinates[101];
    char *ptr;
    int coordinates[4];
    while(fgets(strCoordinates, sizeof(strCoordinates), stdin) != NULL) {
        char *s = strCoordinates;
        for (int x = 0; x < 4; x++) {
            coordinates[x] = strtol(s, &ptr, 10);
            s = ptr;
        }
        u1TapOn = coordinates[0];
        v1TapOn = coordinates[1];
        u2TapOff = coordinates[2];
        v2TapOff = coordinates[3];
        //Calculates (x,y) for (u1, v1) Tap On Coordinates
        x1 = (a * u1TapOn) + (b * v1TapOn);
        y1 = (c * u1TapOn) + (d * v1TapOn);
        //Calculates (x,y) for (u2, v2) Tap Off Coordinates
        x2 = (a * u2TapOff) + (b * v2TapOff);
        y2 = (c * u2TapOff) + (d * v2TapOff);
        //Calculates the fare for each line of the input
        fare = abs(x1 - x2) + abs(y1 - y2);
        printf("%d\n", fare);   
    }       
    return 0;
}

计算的逻辑是,该文件代表一群人,他们拿着卡片,上面有钱。他们有有效的卡号、姓名、余额、坐标来计算行进距离以计算费用。

脚本应该查看谁的余额中没有足够的钱来支付费用,然后打印他们的名字。脚本应该带参数来调整费用值

我会尝试用 awk 给你一个关于这个特定案例的评论示例:(警告未经测试的代码)

#!/usr/bin/awk -f    
BEGIN { FS =[:,] } # Set the Field Separator

{  #Do this for each line (no selector before the block)
  "./myprogram"     | getline fee[] # Get the fee value by calling the program with the 4 last fields from line and startan array of fee with username as key for later use
  close("./myprogram") # To empty the buffer and avoid errors after
  resultingbalance[]=  - fee[] # some math to get the resulting balance for user, same into an array with user as key
} 

END { # Important keyword, this code will run after the end of file has been reached
  for (i in resultingbalance) { # loop over the array
    if ((resultingbalance[i]) < 0) { # is the relusting balance negative ?
      print i," can't pay its travel. Fee:",fee[i]," Balance at  end:",resultingbalance[i] # if yes, print the key (username), the fee and the balance at end accessign the arrays
    }
  }
}

希望这会有所帮助

全部在 awk 中

awk -F[,:] -vx="2,3,4,5" '
{
        split(x,a)
        x1=(a[1]*)+(a[2]*)
        y1=(a[3]*)+(a[4]*)
        x2=(a[1]*)+(a[2]*)
        y2=(a[3]*)+(a[4]*)
        fare=(x1-x2)+(y1-y2)
        fare<0&&fare*=-1}
fare>{print }
' test

如果你想使用你的 c 程序,使用 while 循环可能会更好

while read line;do
        fare=$(awk -F[:,] '{===""}1' <<< "$line" | tester.c 2 3 4 5)
        name=$(awk -F[:,] '{print }' <<< "$line" )
        balance=$( awk -F[:,] '{ print  }' <<< "$line")
        ((fare > balance)) && echo $name
done < test

输出

paul
greg

说明

Awk

-F[,:] -vx="2,3,4,5"

将字段 sep 设置为 ,;
将变量 x 设置为要在计算中使用的值。如果在 -vx=",,,"

等另一个脚本中,也可以将它们作为参数传递
split(x,a)

这会将传入 x 的参数拆分为数组 a 中的单独数组变量。它通过根据我们之前制作的字段分隔符拆分 x 来创建这些。

x1=(a[1]*)+(a[2]*)
...
fare=(x1-x2)+(y1-y2)

基于 c 程序逻辑的计算。

fare<0&&fare*=-1}

如果为负数,则转换为正数。

fare>{print }

如果 field 3 低于票价,则打印 field 2 中的姓名。

Loop

while read line;do
...
done < test

对于文件测试中的每一行

fare=$(awk -F[:,] '{===""}1' <<< "$line" | tester.c 2 3 4 5)

删除前 3 个字段,当字段更改时,(g)awk 会自动重新编译该行。默认的输出字段分隔符是 space,最后 4 个字段以正确的格式传送到 tester.c。

<<< 是一个 here 字符串,它将字符串传递给 awk,就好像它是一个 file/stdin。这样我们就可以把每一行分别传给awk了。

name=$(awk -F[:,] '{print }' <<< "$line" )
balance=$( awk -F[:,] '{ print  }' <<< "$line")

设置其他变量的概念相同。

((fare > balance)) && echo $name

((...)) 是允许执行数学方程和比较的 let 命令。

&& 像这样使用意味着不执行下一个命令,除非第一个 returns true

echo $name 不言自明。

需要更多信息请告诉我:)


资源

http://wiki.bash-hackers.org/commands/builtin/let(令((...))https://www.gnu.org/software/gawk/manual/html_node/(awk 的东西) http://tldp.org/LDP/abs/html/x17837.html(这里是字符串<<<