转义 shell 命令的 gawk 变量

转义 shell 命令的 gawk 变量

我正在尝试运行一个小的 gawk 脚本,它将使用system().我想获取文件列表find并运行脚本,如下所示:

find <arguments> -printf "%f\n" | script.awk

问题是这些文件中包含特殊字符,例如空格、引号和括号。例如:

$ ls
'Aujourd'\''hui C'\''est Toi (Orchestral).flac'

我尝试了各种引用,如下所示:

system("<command> \""$0"\"")

和这个:

system("<command> \'"$0"\'")

我收到各种各样的错误,其中一些错误来自sh -c,一些来自gawk......

有没有办法将记录$0或任何其他变量从 gawk 脚本传递到 shell 命令,而不会遇到所有这些问题?

笔记:我知道暂时重命名文件可能会更容易,但我发现避免它更具挑战性。

编辑:

建议的答案都没有解决我的问题,因此这里是问题的更具体描述:我正在尝试运行一个使用的命令2awk 变量。例子:

如果我运行:

system("metaflac --show-tag=ARTIST \""FILE"\"")

我没有收到错误,因为我引用了FILE并且因为它不包含双引号,所以一切正常。

但如果我跑:

system("metaflac --set-tag=ARTIST="AWK_VAR_WITH_ARTIST_VALUE" "\"FILE\")

即使当我引用它时,我也会收到错误消息,指出metaflac找不到 flac 文件。当阅读错误消息时,我看到文件名被分成单独的单词。

答案1

system("<command> \"$0\"")您可以用 awk 写入进程的能力来替换,print $0 | "pre;<command> \"$v\""部分会将 stdin 读入 shell 变量 v。在 bash 中,这将是read -r v.例如,你最终会得到这样的结果:

awk 'BEGIN{ cmd="read -r v; ls -ld \"$v\"" }
     { print $0 | cmd; close(cmd); }'

如果你想处理可怕的事情,比如文件名中的换行符,你可以在 find 中使用 print0 路径,如果你的 awk 接受RS='\0',你可以使用 bash:

find . -print0 |
awk -v RS='\0' '
 BEGIN{ cmd="read -r -d \"\" v; ls -ld \"$v\"" }
 { print $0 "\x00" | cmd; close(cmd); }'

答案2

对于空格和单引号的特定情况,将字符串用双引号括起来应该足够了:

$ find -name 'Aujour*' -printf "%f\n" | awk '{system("ls -l \""$0"\"")}'
-rw-rw-r-- 1 user user 0 May 26 11:27 Aujourd'hui C'est Toi (Orchestral).flac

或者,如果您的 shell 提供了 shell-quote 格式说明符,您可以考虑使用它来代替 的findinternal -printf

$ find -name 'Aujour*' -exec printf '%q\n' {} \; | awk '{system("ls -l "$0)}'
-rw-rw-r-- 1 user user 0 May 26 11:27 ./Aujourd'hui C'est Toi (Orchestral).flac

help printf例如来自bash

%q  quote the argument in a way that can be reused as shell input

相关内容