轉義 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 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

相關內容