AWK多场分离器和变量

时间:2015-03-30 09:51:06

标签: bash shell awk field sh

我正在尝试使用从shell传入数字的字段以及最后四个字段在awk中执行计算

e.g。我像这样调用我的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="$1"

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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

在脚本的示例调用中,您没有为位置参数$6及其上面传递足够的参数来定义。这导致您的错误消息看起来像illegal field $(),因为v1是一个空字符串,因此您尝试获取没有数字的字段。

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

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

您的代码还有其他一些问题值得一提。引用你的shell变量!这可以防止在更复杂的变量上进行单词拆分的问题。如果你的论点是没有空格的数字,这不会有任何区别,但它也没有任何伤害,并且是一个很好的做法。您已定义file,因此我使用了$1而不是awk -F'[:,]' -v u1="$2" -v v1="$3" -v u2="$4" -v v2="$5" '{ print "u1 =", u1 }' "$file"

结合这些变化,我们最终会得到这样的结果:

{{1}}

答案 1 :(得分:0)

大约一行:

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

这里$ 5,$ 6,$ 7和$ 8是bash位置参数而不是awk字段位置。 根据命令行,您在脚本中有5个参数:

./myProgram myFile.txt 1 2 3 4

$1 = myFile.txt
$2 = 1
$3 = 2
$4 = 3
$5 = 4
$6 = 
$7 =
$8 =

这就是为什么awk仅在通知$v1时提醒您,因为它等同于$并且不是字段值。

如果我理解你的问题,你希望获得最后4个参数匹配值的行:

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

NF是字段数,减3表示结束前的4字段。