我已经在bash中编写了一个名为 trace()的通用记录器函数,其第三个参数以及其他内容应该以文本形式标记和打印,保留任何嵌入的换行符。但它并没有。 我正在寻找类似于echo命令的效果,并按预期执行(在下面尝试过)。 看起来像俱乐部在一起的事情应该归咎于($ {@:3})?
<input type="date">
试验/输出:
timeStamp() { echo `date "+%Y-%m-%d %H:%M:%S:%3N %Z"` ;}
trace() {
lineNum=$1
traceType=$2
traceText=${@:3} #Input Parameters 3rd and beyond
#echo -en "[${lineNum}][$(timeStamp)][${traceType}]: ${traceText}"
#printf "[%s][%s][%s]: %s\n" ${lineNum} "$(timeStamp)" ${traceType} "${traceText}"
printf "[${lineNum}][$(timeStamp)][${traceType}]: ${traceText}"
}
答案 0 :(得分:2)
问题确实在traceText=${@:3}
。通常情况下,$@
相当于$1 $2 $3...
(以及${@:3}
到$3 $4 $5...
),并且因为它不是双引号,所以每个都经过分词和通配符扩张。但是在var=$@
的情况下,它无法为var
分配多个值,因此单词拆分和通配符扩展会被抑制......但显然不完全。它显然做了足够的单词拆分,将换行符转换为空格。
我不清楚这是不是一个错误;由于$@
(将每个参数视为单独的项目)与=
(只能分配一个值)之间的冲突,IMO这种情况实际上没有意义。 IMO您应该使用的是traceText="${*:3}"
,这是明确的 - 双引号明确地抑制了单词拆分和通配符扩展,而$*
意味着将所有参数与空格(或任何IFS
的第一个字符是)。
在我的测试中(使用bash v3.2.57),所有这些都按预期工作:
traceText=${*:3}
traceText="${*:3}"
traceText="${@:3}"
唯一产生奇怪结果的是@
而没有双引号。
答案 1 :(得分:0)
除了评论之外,您还可以完全重写trace()
以包含date
的命令替换,并只使用位置参数在printf
格式字符串中。例如:
trace() {
printf "[$1]$(date "+%Y-%m-%d %H:%M:%S:%3N %Z")][$2]: ${@:3}"
}
示例使用/输出
$ trace 123 "some error" "this
is my
multi-line
text
"
[123]2017-08-04 01:01:29:765 CDT][some error]: this
is my
multi-line
text
注意:可以传递的位置参数的数量有限制,因此如果您的多行文字超出限制,trace
不管用。请参阅:Bash command line and input limit