在 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)