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个字段
我正在尝试使用从 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个字段