Linux 在bash参数中保留引号
我正在制作一个bash脚本,它将打印复杂的参数并将其传递给另一个外部程序Linux 在bash参数中保留引号,linux,bash,Linux,Bash,我正在制作一个bash脚本,它将打印复杂的参数并将其传递给另一个外部程序 ./script -m root@hostname,root@hostname -o -q -- 'uptime ; uname -a' 如何打印原始参数,如下所示: -m root@hostname,root@hostname -o -q -- 'uptime ; uname -a' 使用$@和$*删除正常运行时间周围的单引号;uname-一种可能导致意外结果的。我的脚本不需要解析每个参数。我只需要打印/记录参数字符
./script -m root@hostname,root@hostname -o -q -- 'uptime ; uname -a'
如何打印原始参数,如下所示:
-m root@hostname,root@hostname -o -q -- 'uptime ; uname -a'
使用$@
和$*
删除正常运行时间周围的单引号;uname-一种可能导致意外结果的。我的脚本不需要解析每个参数。我只需要打印/记录参数字符串,并将它们准确地传递给另一个程序
我知道我可以用类似于
“'uptime;uname-a'”
的东西来转义引号,但我不能保证用户会这么做 如果用户以以下方式调用您的命令:
./script 'foo'
给脚本的第一个参数是不带引号的字符串
foo
。您的脚本无法将其与任何其他方法区分开来,通过这些方法可以将foo
作为参数(例如/script$(echo foo)
或/script foo
或/script“foo”
或/script\f\o”“”o
) 在将参数传递给脚本之前,引号会被删除,所以现在保存它们已经太迟了。您可以做的是在将参数传递给内部命令时保留它们的效果,并重新构造用于打印的参数的等效引用/转义版本
对于将参数传递给内部命令“$@”
——使用双引号,$@保留原始分词,这意味着内部命令接收的参数列表与脚本接收的参数列表完全相同
对于打印,可以在bash的printf命令中使用%q格式来重建引用。请注意,这并不总是重建原始的引号,而是构造一个等效的引号/转义字符串。例如,如果您传递了参数“正常运行时间”;uname-a'它可能会打印正常运行时间\\\\uname \-a或“正常运行时间;uname-a”
或任何其他等效物(类似示例见@William Pursell的答案)
下面是一个使用这些的示例:
printf "Running command:"
printf " %q" innercmd "$@" # note the space before %q -- this inserts spaces between arguments
printf "\n"
innercmd "$@"
如果要打印参数列表,使其尽可能接近用户可能输入的内容:
#!/bin/bash
chars='[ !"#$&()*,;<>?\^`{|}]'
for arg
do
if [[ $arg == *\'* ]]
then
arg=\""$arg"\"
elif [[ $arg == *$chars* ]]
then
arg="'$arg'"
fi
allargs+=("$arg") # ${allargs[@]} is to be used only for printing
done
printf '%s\n' "${allargs[*]}"
#/bin/bash
字符='[!“#$&()*,;?\^`{124}]'
对于arg
做
如果[[$arg==*\'*]]
然后
arg=\“$arg”
elif[[$arg==*$chars*]]
然后
arg=“$arg”
fi
allargs+=(“$arg”)#${allargs[@]}仅用于打印
完成
printf'%s\n'${allargs[*]}
它不是完美的。像
'\'''
这样的参数比合理的参数更难适应。正如其他人所提到的,当您访问脚本内部的参数时,要知道调用时引用了哪些参数为时已晚。但是,您可以重新引用包含空格或其他特殊字符的参数,这些参数需要引用才能作为参数传递
下面是一个基于的Bash实现,它可以做到这一点:
function quote() {
declare -a params
for param; do
if [[ -z "${param}" || "${param}" =~ [^A-Za-z0-9_@%+=:,./-] ]]; then
params+=("'${param//\'/\'\"\'\"\'}'")
else
params+=("${param}")
fi
done
echo "${params[*]}"
}
您的示例稍微更改为显示空参数:
$ quote -m root@hostname,root@hostname -o -q -- 'uptime ; uname -a' ''
-m root@hostname,root@hostname -o -q -- 'uptime ; uname -a' ''
eval./script-mroot@hostname,root@hostname-o-q--“正常运行时间;取消配置-a”
使用${@Q}获得一个简单的解决方案。要进行测试,请将下面的行放入脚本bigQ中
#!/bin/bash
line="${@@Q}"
echo $line
./bigQ 1 a "4 5" b="6 7 8"
'1' 'a' '4 5' 'b=6 7 8'
无法保证用户将转义引号。根据此答案:,虽然
echo$@
不打印引号,但$@会“在后台传递引号”。我试着写了两个脚本:第一个脚本将“$@”传递给第二个脚本,而第二个脚本打印“$1”,它工作起来很有趣。我想我在打印时运气不好,但是传递“$@”
似乎仍然允许外部程序正确解析参数。“$@”
在打印时不会保留引号谢谢编辑。%q
不完全是我需要的,但它很有用。谢谢,谢谢。我更喜欢将空格放在%q之后。这在某些情况下有效,但在其他情况下无效。差不多,但不完全适用于我的用例。虽然此代码可以回答问题,但提供有关此代码为什么和/或如何回答问题的附加上下文可以提高其长期价值。虽然此代码可以回答问题,但提供有关此代码为什么和/或如何回答问题的附加上下文可以提高其长期价值。我建议你检查一下SO和全面的from。听起来你对简单的回答有兴趣!