【问题标题】:Columns and Arguments AWK Parameters in Shell ScriptingShell 脚本中的列和参数 AWK 参数
【发布时间】:2015-06-02 22:18:10
【问题描述】:

我想获取位置参数作为 .sh 文件的参数,并且还想从文本文件中获取 awk 的字段。我发现我需要为两者都使用 $1-$9 并且可以在 awk 中使用相同的数字 $() 作为定位参数,它仍然有效。

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

./myProgram myFile.txt 1 2 3 4

然后在我的 shell 脚本中,我想使用 awk 来引用这样的文本文件中的字段,特别是 1,2:3,4 最后四个字段。

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

到目前为止,我已经很接近了,我不知道为什么我不能使用我的 awk 脚本在各个领域中走得更远?

【问题讨论】:

标签: bash unix awk arguments sh


【解决方案1】:

更新:似乎 OP 的问题源于混淆了 shell 参数$1$2,...)与 Awk 中的 >input-field 变量 - 可以看起来相同,但完全不相关。
具体来说,错误的假设是如果将n 参数传递给shell 脚本,Awk 的输入字段编号将以n+1 开头。


下面的sn-p——原来写在OP之前给问题添加了更多代码——演示了shell参数和Awk变量的相互作用,后面有详细的解释.

具体来说,它根据shell参数$2$3的值分别定义了Awk变量fi1fi2,其中包含1-基于 字段索引 相对于文件 $file 中的行。

然后,在 Awk 程序中,存储在 fi1fi2 中的字段索引首先按原样(没有 $ 前缀)打印它们自己的值,然后到通过添加 $ 来引用相应的输入行 fieldsAwk 中的变量引用不是 $-前缀 - $ 仅用于引用 字段)。

#!/usr/bin/env bash

file="$1"

awk -F'[:,]' -v fi1=$2 -v fi2=$3 \
  '{ print "Field #" fi1 " + field #" fi2 " =", $fi1 + $fi2 }' "$file"
  • shell 和awk 是独立的世界,看不到彼此的变量。
    • 通过访问ENVIRON 关联数组,您可以看到awk 中的环境 变量,但是您看不到shell 变量。
    • 可以通过传递带有shell变量引用的双引号字符串隐式地将shell变量值“烘焙”到awk程序中——这些引用被扩展了之前 awk 看到程序 - 但这很快就会让人困惑,应该避免。
    • 相反,将值 backawk 传递到 shell 的唯一方法是让 awk 打印到 stdout 并使用 shell 命令替换将结果捕获到 shell 变量中。李>
  • 您可以使用-v 选项的实例将shell 参数和变量的值传递给awk 变量,如上所示。
    • 这里我们知道值是数字,所以我们不需要严格地用双引号引起来。参考资料,但一般建议这样做。
  • awk 中,其变量被引用没有$ 前缀,而$用于引用输入字段 em>
    • $fi1,可能有点令人困惑,因此意味着:获取索引存储在awk 变量 fi1 中的输入字段(前缀$)(相比之下,按原样使用fi1,不带前缀,将返回索引)。
  • awk 中的字段索引始终基于1,相对于每一行输入。
    • 例如,在awk 内部,$1 指的是当前输入行的第一个字段,尽管它看起来与第一个脚本相同/shell中的函数参数,它们之间绝对没有任何关系。
    • 此外,$0 包含整个当前输入行,NF 包含数字(计数)输入字段。

【讨论】:

  • 我似乎到了那里,但现在不确定我的 awk 行出了什么问题@mklement0
  • @JoshuaVernon:现在的问题是,您似乎在创建 没有值 的 Awk 变量,这会导致基于该值的字段引用 - $<varname> - 失败(如果varname 评估为空字符串,则$ 本身显然不是有效的字段索引)。您的特定错误消息表明未设置 shell 参数 $6$7$8。请注意,在您的调试代码中,您仅通过$5 进行打印,而您的 Awk 命令最多基于$8 定义变量。
  • 你是对的。我现在学会了使用 $(NF-1),这似乎在 awk 中运行良好
猜你喜欢
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 2012-05-21
  • 2011-11-19
  • 1970-01-01
  • 2020-07-18
  • 2018-11-18
  • 2020-11-27
相关资源
最近更新 更多