我想弄清楚如何编写一个独立的 awk 脚本文件。
我认为它类似于一个独立的 bash 脚本文件:
#! /usr/bin/awk -f
BEGIN{
for (i = 0; i < ARGC; i++)
printf "%s ", ARGV[i]
printf "\n"
}
{print $0}
Run Code Online (Sandbox Code Playgroud)
我试图弄清楚如何在 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)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
为什么是-f必要的?
谢谢。
AWK 期望它的参数是脚本的文本,或者-f后跟包含要运行的脚本的文件的名称,在这两种情况下,都可以选择后跟要处理的文件的名称。
这解释了为什么你需要-f在 shebang 行中:没有它,AWK 认为你的脚本的文件名本身就是要运行的 AWK 语句。
关于参数处理,AWK 程序可以根据需要进行自己的参数处理。您的脚本由于该{print $0}行而失败:这指示解释器从其输入(命令行上命名的文件,因为您已指定一些文件)中读取每一行,并根据块中的说明对其进行处理。如果删除该行,则不会出现任何错误。您可以处理BEGIN和清理参数ARGV,使其只包含输入文件;那么 AWK 就不会抱怨了。
尝试完全进行自己的论证和输入处理,可能意味着忽略许多使 AWK 如此有用的东西;如果你想这样做,你不妨使用 Perl。
(请注意,shebang 处理意味着您可以将简单的 AWK 脚本存储在它们的文件名中,这避免了必须为脚本找到巧妙的名称——而不是任何人都应该这样做......)
一个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
Run Code Online (Sandbox Code Playgroud)
命令行检查选项以第一个非选项参数结束:
$ ./script.awk ~/.profile -vvar=hello
ARGV[2] = -vvar=hello
ARGV[0] = awk
ARGV[1] = /home/kk/.profile
var =
Run Code Online (Sandbox Code Playgroud)
为了awk对任何事情有用,它需要输入数据。这些数据通常来自一个或多个在命令行中命名的输入文件,或者来自在标准输入流上发送的数据。
除了BEGIN和END块之外,awk脚本中的每个块都会依次应用于输入数据的每条记录(默认为每行)。
小智 5
awk 脚本期望其命令行参数是什么?为什么它期望 arg1 作为输入文件?
awk基于模式的规则需要输入。当程序的这部分处理开始时,awk开始使用参数作为文件名(如果没有给出文件名,则使用标准输入)。
在此步骤之前,您可以使用块中给定的参数执行任何操作BEGIN。
我认为,这些小例子可以帮助您入门:
$ cat a.awk
#!/usr/bin/awk -f
BEGIN {
i=1
while( i in ARGV )
print ARGV[i++]
}
Run Code Online (Sandbox Code Playgroud)
a.awk只有一个BEGIN块,没有基于模式的规则。awk不需要文件,因此不使用给定的参数作为文件名:
$ ./a.awk poit --zort -troz narf
poit
--zort
-troz
narf
Run Code Online (Sandbox Code Playgroud)
如何处理这些是您的决定。
如果您也希望基于模式的规则处理作为参数给出的文件,则需要删除块中使用的所有参数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
}
Run Code Online (Sandbox Code Playgroud)
不带选项运行示例:
$ ./b.awk a.awk
#!/usr/bin/awk -f
BEGIN {
i=1
while( i in ARGV )
print ARGV[i++]
}
Run Code Online (Sandbox Code Playgroud)
使用--toupper选项运行示例:
$ ./b.awk --toupper a.awk
#!/USR/BIN/AWK -F
BEGIN {
I=1
WHILE( I IN ARGV )
PRINT ARGV[I++]
}
Run Code Online (Sandbox Code Playgroud)