error
我的POSIX sh
shell 代码中有一个函数。它基本上看起来像
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
为提醒。如果您将其用作:
$arg
你会因为类似的值引起问题%99999999s
理想情况下,您希望告诉 shellcheck 忽略 of 的用法,
printf
并让它标记您的printf
where 第一个参数包含变量的用法。几点注意事项:
printf
了两次,那将是至少 2 个write()
系统调用。不太可能有任何区别,请注意,printf
像bash
's 这样的一些实现在某些情况下也会执行多个系统调用。我正在考虑的问题是错误消息的两个部分与另一个并行运行的命令的输出交织在一起。在
error "%s\n" error1 error2
前缀中只会输出第一个错误。如果你想这样做,那很好。你也可以这样做:将前缀添加到格式中,因此每次重用格式时都会输出(这也将解决多重
write()
问题)。utility
但是,如果您想成为变量,那将行不通。
不行,因为它会在$0
contains%
或\
.和
在格式被重用的情况下不起作用(这意味着用户需要将%<n>$d
指令偏移一个(我不建议使用这些指令,因为它们不可移植))。除了手动转义
\
and之外,我想不出任何简单的解决方法,即使这并不像许多实现那样容易,您还需要转义在其他字符中找到的字节(对于像 BIG5 这样的字符集或GB18030有一些)。%
$PROG_NAME
printf
0x5c
\