AWK 多字段分隔符和变量

AWK Multiple Field Separators and Variables

我正在尝试使用从 shell 传入数字的字段以及最后四个字段

在 awk 中执行计算

例如我这样称呼我的 shell 脚本

./myProgram myFile.txt 1 2 3 4

然后在我的 shell 脚本中,我想使用 awk 来引用文本文件中的字段,特别是最后四个字段。 $(NF-3) - $(NF)

0000000022:trevor:736:1,2:3,4
0000000223:john:73:5,6:7,8
0000002224:eliza:54:9,8:7,6
0000022225:paul:22:5,4:3,2
0000222226:chris:0:1,2:3,4

所以我可以遍历字段,但是当我这样做时,因为有两种类型的字段分隔符,它似乎不起作用。

到目前为止我的 shell 脚本:

#! /usr/bin/env bash

file=""

awk -F'[:,]' -v u1= -v v1= -v u2= -v v2= \ '{ print "u1 =", $u1 }' 
awk -F'[:,]' -v u1= -v v1= -v u2= -v v2= \ '{ print "v1 =", $v1 }' 
awk -F'[:,]' -v u1= -v v1= -v u2= -v v2= \ '{ print "u2 =", $u2 }' 
awk -F'[:,]' -v u1= -v v1= -v u2= -v v2= \ '{ print "v2 =", $v2 }' 

echo "Argument #1 =" 
echo "Argument #2 =" 
echo "Argument #3 =" 
echo "Argument #4 =" 

这是我从终端获得的输出:

u1 = 1
u1 = 5
u1 = 9
u1 = 5
u1 = 1
v1 = awk: illegal field $(), name "v1"
 input record number 1, file database.txt
 source line number 1
u2 = awk: illegal field $(), name "u2"
 input record number 1, file database.txt
 source line number 1
v2 = awk: illegal field $(), name "v2"
 input record number 1, file database.txt
 source line number 1
Argument #1 = 1
Argument #2 = 2
Argument #3 = 3
Argument #4 = 4

当您在 awk 中使用 $N 时,它将检索字段 N。您可以将它与将参数传递给 awk 结合使用,就像您访问 shell 变量中定义的字段编号一样。主要问题似乎是您正在传递尚未在脚本中设置的变量。

在您的脚本调用示例中,您没有为要定义的位置参数 </code> 及以上传递足够的参数。这就是导致你的错误消息看起来像 <code>illegal field $() 的原因,因为 v1 是一个空字符串,所以你试图获取一个没有数字的字段。

NF是awk中的一个特殊变量,它包含字段的个数,所以要访问最后四个字段,可以使用$(NF-3)$(NF-2)$(NF-1), 和 $NF.

在 awk 命令之前有一个 \ 没有做任何有用的事情,所以我也删除了它。

您的代码还有一些其他问题也值得一提。引用你的 shell 变量!这可以防止在更复杂的变量上出现分词问题。如果你的论点是没有空格的数字,这不会有任何区别,但也没有坏处,是一个很好的实践。您定义了 file,所以我用它代替了 </code>。</p> <p>结合这些变化,我们最终得到这样的结果:</p> <pre><code>awk -F'[:,]' -v u1="" -v v1="" -v u2="" -v v2="" '{ print "u1 =", u1 }' "$file"

只有一行:

awk -F'[:,]' -v u1= -v v1= -v u2= -v v2= \ '{ print "u1 =", $u1 }'

此处 $5、$6、$7 和 $8 是 bash 位置参数,而不是 awk 字段位置。 根据您的命令行,您的脚本有 5 个参数:

./myProgram myFile.txt 1 2 3 4

 = myFile.txt
 = 1
 = 2
 = 3
 = 4
 = 
 =
 =

这就是为什么 awk 仅在调用 $v1 时提醒您,因为它等同于 $ 而不是字段值。

如果我正确理解了你的问题,你希望得到最后 4 个参数匹配这些值的行:

awk -F'[:,]' '{ print "u1=",$(NF-3),"v1=",$(NF-2),"u2=",$(NF-1),"v2=",$NF }' ""

NF为字段数,减3得到结束前的第4个字段