将 $@ 传递给命令,保留引号

Tom*_*han 7 bash

我正在尝试git使用此处概述的方法修改 的行为,但我在如何正确传递 的内容$@而不丢失原始输入的引号方面遇到了困难。

基本上,我有这个:

# foo.sh

#!/bin/bash
cmd=$1
shift
args=$@
if [ $cmd == "bar" ]; then args=('--baz' "${args[@]}"); fi
echo git $cmd ${args[@]}
Run Code Online (Sandbox Code Playgroud)

但是当我运行时./foo.sh bar -a "one two three",它输出(因此会运行), ./foo.sh bar --baz -a one two,而不是./foo.sh bar --baz -a "one two"我需要的。

我无法弄清楚如何正确传递$@给另一个命令并保留引用的参数。是否可以?如何?

Kus*_*nda 13

使用"${args[@]}"时假设它args是一个数组,但它不是。

对于args是一个数组,你必须分配给它一个数组赋值,如

args=( "$@" )
Run Code Online (Sandbox Code Playgroud)

要在 expand 时单独引用数组的元素${args[@]},您必须双引号扩展(就像 with "$@"):

echo git "$cmd" "${args[@]}"
Run Code Online (Sandbox Code Playgroud)

在这个简单的例子中,args根本不需要单独的数组:

#!/bin/sh

cmd=$1
shift

if [ "$cmd" = "bar" ]; then
   set -- --baz "$@"
fi

echo git "$cmd" "$@"
Run Code Online (Sandbox Code Playgroud)

请注意,echo上面的命令不会输出引号。但是您可以放心,echo得到正好两个参数 ( gitand $cmd) 加上此时有很多东西$@。这是因为 shell 在执行命令之前会删除该命令的引号。您可以将其与例如echo "one two" three输出的内容进行比较。

输出目视检查命令的更好方法可能是

printf 'Arg: %s\n' git "$cmd" "$@"
Run Code Online (Sandbox Code Playgroud)

这会将每个单独的参数打印到printf自己的行(以字符串为前缀Arg:)。

您的git命令git "$cmd" "$@"(或者git "$cmd" "${args[@]}"如果您使用单独的数组)将正确运行(例如,假设变量有意义,普通git没有bar--baz选项的子命令)。

有关的: