在 AWK 脚本内部,我可以将变量作为参数传递给外部实用程序:
awk 'BEGIN {
filename = "path_to_file_without_space"
"file " filename | getline
print $0
}'
Run Code Online (Sandbox Code Playgroud)
但如果变量包含空格,
awk 'BEGIN {
filename = "path to file with spaces"
"file " filename | getline
print $0
}'
Run Code Online (Sandbox Code Playgroud)
我收到错误
file: cannot open `path' (No such file or directory)
Run Code Online (Sandbox Code Playgroud)
建议在空格上分割参数,这与 shell 在空格上分割未加引号的变量的方式非常相似。我想通过将 shell 的 IFS 设置为 null 来禁用 shell 字段分割,如下所示
"IFS= file " filename | getline
Run Code Online (Sandbox Code Playgroud)
或者在运行 AWK 命令之前将 IFS 设置为 null,但这两个选项都没有任何区别。如何避免这种字段分裂?
您必须引用文件名:
awk 'BEGIN {
filename = "path to file with spaces"
"file \"" filename "\"" | getline
print
}'
Run Code Online (Sandbox Code Playgroud)
或者,正如评论中所建议的,为了便于阅读,
awk 'BEGIN {
DQ = "\042" # double quote (ASCII octal 42)
filename = "path to file with spaces"
"file " DQ filename DQ | getline
print
}'
Run Code Online (Sandbox Code Playgroud)
或者,假设这是一个更大awk程序的一部分,
BEGIN {
SQ = "\047"
DQ = "\042"
}
BEGIN {
name = "filename with spaces"
cmd = sprintf("file %s%s%s", DQ, name, DQ)
cmd | getline
close(cmd)
print
}
Run Code Online (Sandbox Code Playgroud)
也就是说,完成后关闭该命令以保存打开的文件句柄。在单独的块中设置方便的“常量” BEGIN(这些块按顺序执行)。sprintf使用到单独的变量中创建命令。(这些东西中的大多数显然是针对更长或更复杂的awk程序,需要提供一种可读的结构以便维护;人们也可以想象编写一个引用字符串的dquote()andsquote()函数)
“管道”的左侧将计算为文字字符串
file "path to file with spaces"
Run Code Online (Sandbox Code Playgroud)
基本上, usingcmd | getline使awk调用sh -c带有单个参数,即 string cmd。因此,必须正确引用该字符串才能使用 执行sh -c。
技术细节可在POSIX 标准中找到:
expression | getline [var]从命令输出通过管道传输的流中读取输入记录。如果当前没有打开流,则应创建该流并将 的值
expression作为其命令名称。创建的流应等效于通过调用函数创建的流,popen()其中表达式的值作为命令参数,值r作为参数mode。只要流保持打开状态,expression计算结果为相同字符串值的后续调用就应从流中读取后续记录。流应保持打开状态,直到close使用计算结果为相同字符串值的表达式调用函数为止。那时,流将被关闭,就像通过调用该pclose()函数一样。如果var省略,$0则应NF设置;否则,var应设置,并且如果合适,应将其视为数字字符串(请参阅 awk 中的表达式)。
这里指的函数popen()是Cpopen()库函数。这安排了给定的字符串由 执行sh -c。
system()如果使用带空格的文件名执行命令,您将遇到完全相同的问题,但在这种情况下system(),将调用 C 库的函数,该函数也sh -c以类似的方式进行调用popen()(但 I/O 流的管道不同)。
因此,如果使用单个参数调用,任何设置都IFS无济于事sh -c
file path to file with spaces
Run Code Online (Sandbox Code Playgroud)