Quoting

printf 類似工作的包裝器,用於為錯誤消息添加前綴和重定向

  • April 19, 2018

error我的POSIX shshell 程式碼中有一個函式。它基本上看起來像

error () {
   printf 'utility: ERROR: ' >&2
   printf "$@" >&2
}

第二個printf使我可以使案例如呼叫該函式

error 'Something relating to "%s" went wrong!\n' "$thing"
exit 1

並且該函式將在消息前面加上字元串utility: ERROR:,並安排所有發送到標準錯誤的內容,而我仍然可以像使用printf.

顯然,ShellCheck抱怨第二個printf,說

SC2059:不要在 printf 格式字元串中使用變數。使用 printf “..%s..” “$foo”

做我所做的事情並忽略此警告是否“安全”(甚至可能通過程式碼中的註釋禁用它)?# shellcheck disable=SC2059注意,我總是按照我原本使用的方式來使用我的函式error即使用靜態單引號的第一個參數。printf

“安全嗎?” printf這裡的意思是“我的函式是否以適當的方式充當類似工作的包裝器(除了重定向) ?”

這是安全的,因為您確實打算在這裡將格式作為參數傳遞。但是你在使用函式時必須記住它是格式。所以也許你應該把你的函式命名errorf為提醒。

如果您將其用作:

error "invalid arg: $arg"

$arg你會因為類似的值引起問題%99999999s

理想情況下,您希望告訴 shellcheck 忽略 of 的用法,printf 讓它標記您的printfwhere 第一個參數包含變數的用法。

幾點注意事項:

  • 因為你呼叫printf了兩次,那將是至少 2 個write()系統呼叫。不太可能產生任何影響,請注意,printfbash’s 這樣的一些實現在某些情況下也會執行多個系統呼叫。我正在考慮的問題是錯誤消息的兩個部分與另一個並行執行的命令的輸出交織在一起*。*
  • error "%s\n" error1 error2前綴中只會輸出第一個錯誤。如果你想這樣做,那很好。你也可以這樣做:
errorf() { printf "utility: ERROR: $@" >&2; }

將前綴添加到格式中,因此每次重用格式時都會輸出(這也將解決多重write() 問題)。

utility但是,如果您想成為變數,那將行不通。

PROG_NAME=${0##*/}
errorf() { printf >&2 "$PROG_NAME: ERROR: $@"; }

不行,因為它會在$0contains%\. 和

PROG_NAME=${0##*/}
錯誤(){
格式=$1; 轉移
printf >&2 "%s: 錯誤: $format" "$PROG_NAME" "$@"
}

在格式被重用的情況下不起作用(這意味著使用者需要將%<n>$d指令偏移一個(我不建議使用這些指令,因為它們不可移植))。 除了手動轉義\and之外,我想不出任何簡單的解決方法,即使這並不像許多實現那樣容易,您還需要轉義在其他字元中找到的字節(對於像 BIG5 這樣的字元集或GB18030有一些)。%``$PROG_NAME``printf``0x5c``\

引用自:https://unix.stackexchange.com/questions/438694