Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 在bash参数中保留引号_Linux_Bash - Fatal编程技术网

Linux 在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-一种可能导致意外结果的。我的脚本不需要解析每个参数。我只需要打印/记录参数字符

我正在制作一个bash脚本,它将打印复杂的参数并将其传递给另一个外部程序

./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。听起来你对简单的回答有兴趣!