我想弄清楚如何编写独立的 awk 脚本文件。
我认为它类似于独立的 bash 脚本文件:
#! /usr/bin/awk -f
BEGIN{
for (i = 0; i < ARGC; i++)
printf "%s ", ARGV[i]
printf "\n"
}
{print $0}
我试图弄清楚如何在 shell 中指定命令行参数并将其传递到脚本中:
$ myscript.awk arg1 arg2 arg3 awk arg1 arg2 arg3 awk: /home/tim/myscript.awk:5: fatal: cannot open file `arg1' for reading (No such file or directory)
awk 脚本期望其命令行参数是什么?为什么它期望
arg1
成为输入文件?命令行参数被传递到 awk 脚本中,并存储在数组 ARGV 中。看我的更新。所以我想命令行参数是根据脚本解释的,而不是
awk
.如果我删除
-f
shebang,即#! /usr/bin/awk
$ myscript.awk arg1 arg2 arg3 awk: cmd. line:1: /home/tim/myscript.awk awk: cmd. line:1: ^ syntax error
为什么是
-f
必要的?
谢谢。
答案1
AWK 期望其参数是脚本的文本,或者-f
后跟包含要运行的脚本的文件的名称,在这两种情况下都可以选择后跟要处理的文件的名称。
这解释了为什么您需要-f
在 shebang 行中:没有它,AWK 会认为您的脚本的文件名本身就是要运行的 AWK 语句。
关于参数处理,AWK 程序可以根据需要进行自己的参数处理。您的脚本因该{print $0}
行而失败:这指示解释器从其输入(命令行上命名的文件,因为您已经指定了一些文件)中读取每一行,并根据块中的说明对其进行处理。如果删除该行,则不会出现任何错误。您可以处理参数BEGIN
并进行清理ARGV
,使其仅包含输入文件;那么 AWK 就不会抱怨了。
尝试完全进行自己的参数和输入处理,可能意味着忽略 AWK 如此有用的许多因素;如果你想这样做,你不妨使用 Perl。
(请注意,shebang 处理意味着您可以在其文件名中存储简单的 AWK 脚本,这避免了必须为脚本找到巧妙的名称 - 并不是任何人都应该这样做......)
答案2
awk 脚本期望其命令行参数是什么?为什么它期望 arg1 作为输入文件?
awk
基于模式的规则需要输入。当程序的这部分处理开始时,awk
开始使用参数作为文件名(如果没有给出文件名,则使用标准输入)。
在此步骤之前,您可以使用块中给定的参数执行任何操作BEGIN
。
我认为,这些小例子可以帮助您入门:
$ cat a.awk
#!/usr/bin/awk -f
BEGIN {
i=1
while( i in ARGV )
print ARGV[i++]
}
a.awk
只有一个BEGIN
块,没有基于模式的规则。awk
不需要文件,因此不使用给定的参数作为文件名:
$ ./a.awk poit --zort -troz narf
poit
--zort
-troz
narf
如何处理这些是您的决定。
如果您也希望基于模式的规则处理作为参数给出的文件,则需要删除块中使用的所有参数BEGIN
:
$ cat b.awk
#!/usr/bin/awk -f
BEGIN {
if( ARGV[1] == "--tolower" ) { cmd = "tr A-Z a-z" ; delete ARGV[1] }
else if( ARGV[1] == "--toupper" ) { cmd = "tr a-z A-Z" ; delete ARGV[1] }
else cmd = "cat"
}
{
print | cmd
}
不带选项运行示例:
$ ./b.awk a.awk
#!/usr/bin/awk -f
BEGIN {
i=1
while( i in ARGV )
print ARGV[i++]
}
使用--toupper
选项运行示例:
$ ./b.awk --toupper a.awk
#!/USR/BIN/AWK -F
BEGIN {
I=1
WHILE( I IN ARGV )
PRINT ARGV[I++]
}
答案3
脚本awk
期望其非选项命令行参数是脚本应执行操作的文件的文件名(如果没有给出,则它对标准输入执行操作)。
因此,当您#!/usr/bin/awk -f
在awk
脚本文件中使用时,这会告诉系统文件本身的文本应该传递到awk -f
.任何其他命令行参数将被解释为输入文件或附加标志awk
:
#!/usr/bin/awk -f
BEGIN {
for (i in ARGV) {
printf("ARGV[%d] = %s\n", i, ARGV[i]);
}
printf("var = %s\n", var);
}
$ ./script.awk -vvar=hello ~/.profile
ARGV[0] = awk
ARGV[1] = /home/kk/.profile
var = hello
命令行检查选项在第一个非选项参数处结束:
$ ./script.awk ~/.profile -vvar=hello
ARGV[2] = -vvar=hello
ARGV[0] = awk
ARGV[1] = /home/kk/.profile
var =
为了awk
对任何事情有用,它需要输入数据。该数据通常来自命令行上命名的一个或多个输入文件,或者来自标准输入流上发送的数据。
除了BEGIN
和END
块之外,脚本中的每个块awk
将依次应用于输入数据的每条记录(默认为每行)。