【问题标题】:bash: quote var with quotesbash:用引号引用 var
【发布时间】:2023-11-28 10:30:01
【问题描述】:

我尝试制作一个用于调试的虚拟脚本。该脚本应将命令和所有参数传递给 syslog。但是当我得到一个带引号的参数时,我只会失败。

#!/bin/sh

set -x
param="$*"

logger -t $0 -p local3.debug "$*"
#logger -t $0 -p local3.debug "$param"
#logger -t $0 -p local3.debug "$(echo "$param")"
#logger -t $0 -p local3.debug "${param//\"/}"
#logger -t $0 -p local3.debug "${param[@]}"

我尝试了一些我发现的变体,但没有任何效果。

# d-iptables -L dkdsdds "ddd"
+ param='-L dkdsdds ddd'
++ echo '-L dkdsdds ddd'
+ logger -t /usr/sbin/d-iptables -p local3.debug '-L dkdsdds ddd'
logger: invalid option -- L

Usage:
 logger [options] [message]

Options:
 -d, --udp             use UDP (TCP is default)
 -i, --id              log the process ID too
 -f, --file <file>     log the contents of this file
 -h, --help            display this help text and exit
 -n, --server <name>   write to this remote syslog server
 -P, --port <number>   use this UDP port
 -p, --priority <prio> mark given message with this priority
 -s, --stderr          output message to standard error as well
 -t, --tag <tag>       mark every line with this tag
 -u, --socket <socket> write to this Unix socket
 -V, --version         output version information and exit

【问题讨论】:

  • 听起来像Bash FAQ 50。你的直接问题是你想要"$@",但我猜它不会把你带到你想去的地方。但就是不想去那里。
  • 我只想去掉 var 中的引号,我可以将它们作为消息传递给记录器
  • 如果您试图将参数逐字转发给其他命令,那么在调用其他命令时只需使用"$@",如三元组所示。如果那 对您正在尝试做的事情起作用(我确信它会),那么编辑您的问题以说明 为什么 您认为它不起作用。
  • 如果您要发布自己的答案,请将其发布为新答案;不要将其编辑到问题中-这样可以对答案进行赞成/反对/评论/等。与问题分开。
  • 对不起,我不想鞭打好的提示,这帮助我找到了自己的方式:)

标签: bash quotes double-quotes


【解决方案1】:

我建议您将脚本更改为 #!/bin/bash 并使用

logger -t $0 -p local3.debug -- "$(printf "%q " "$@")"

您需要--,因此记录器认为-L 不是它的选项之一。

【讨论】:

  • 还不错,但在系统日志中我没有得到引号 -> /usr/sbin/d-iptables: -L dkdsdds ddd :(
  • 你不能:你的 shell 甚至在你的脚本启动之前删除它们
  • 真的确定没办法?! IFS、for 循环还是其他?
  • 是的,非常确定。假设你的 shell 是 bash,在命令启动之前有一个定义的扩展列表。引号删除是这些扩展之一。您的脚本永远不会知道用户如何引用参数。
  • 检查我的答案。保存它们?没门。要在它们被删除(或丢失)后添加它们......是的。
【解决方案2】:

首先,您已将其标记为 bash,但您使用的是 /bin/sh(它是 bourne 或 dash)。接下来,您的记录器正在读取 - 作为参数。只是更好地引用它。

#!/bin/bash

set -x
param="\"$@\""     # quotes removed by the shell

logger -t $0 -p local3.debug "'$param'"  # expand, then strong quote

【讨论】:

  • 为什么要将数组分配给标量变量?
  • 神圣的 Perl 术语,蝙蝠侠! B/c 在这种情况下,数组是一个字符串。事实上,这就是 OP 对待它的方式,我认为没有理由将其设为数组。为什么要将字符串分配给数组?不需要。
  • OP 想要从他们的数组中创建一个字符串,是的,但是param="\"$@\"" 实际上并没有以有用的方式这样做。我的意思是,如果你有set -- "first item" "second item",那么所需的输出大概是一个字符串,它显示了一起引用的那些,对吧?像param="'first item' 'second item'" 这样的东西?你的代码没有做到这一点。
  • ...相比之下,printf -v param '%q ' "$@" 将(在 bash 中)分配类似 param='first\ item second\ item' 的内容,从而明确哪个空格是句法的,哪个空格是字面的。 (在 ksh 中,它会做得更好,遵循 'first item' 'second item' 模型)。
  • ksh 没有密切关系。如果 printf 显示文字/句法并不重要,b/c 记录器会吃掉它们,并且它会在最终产品中被掩盖。此外,logger 接受一个参数——一个字符串作为消息。因此,您在编码时假设存在多个论点,而实际上不可能存在。 ? logger "this is" "messed up" 不是有效行为。