在bash脚本中处理git命令数组

在bash脚本中处理git命令数组,bash,git,Bash,Git,大家好: 我正在编写一个bash脚本来从git repos中提取数据。我有一个数组来存储存储库名称: declare -a arr=( https://"$USER"@stash/repo1.git https://"$USER"@stash/rep2.git ) 我的处理如下: for i in "${arr[@]}" do git clone "$i" ...... git install done 这很有效。现在,我希望能够选择性地指定git分支: declar

大家好:

我正在编写一个bash脚本来从git repos中提取数据。我有一个数组来存储存储库名称:

declare -a arr=(
https://"$USER"@stash/repo1.git
https://"$USER"@stash/rep2.git
)
我的处理如下:

for i in "${arr[@]}"
do
    git clone "$i"
    ......
    git install
done
这很有效。现在,我希望能够选择性地指定git分支:

declare -a arr=(
    -b branch1 --single-branch https://"$USER"@stash/repo1.git
    https://"$USER"@stash/rep2.git
)
阵列处理脚本失败,出现多个错误: -开关“b”需要一个值 -无效的标识符等

什么是正确和简单的方法使其工作?

c.f.printf%s\n${arr[@]}。仅仅因为这些参数在一行上并不能使它们成为一个元素:

您正试图用一个数组做两件事

试试这个-

declare -a arr=(
   "https://$USER@stash/repo1.git#branch1"
   "https://$USER@stash/rep2.git"
)

for i in "${arr[@]}"
do  IFS='#' read url branch <<< "$i"
    if [[ -n "$branch" ]]
    then git clone -b "$branch" --single-branch "$url"
    else git clone "$url"
    :    ......
    git install
done

警告-没有机会对此进行测试。注意Scriptor——当然这意味着你的url不能在任何地方。

如果你删除周围的引号,它可能会起作用

git clone "$i"
所以看起来是这样的:

git clone $i
我认为,对于引号,shell应将所有行视为一个参数,而不是多个:

git clone "-b branch1 --single-branch https://"$USER"@stash/repo1.git"
这看起来不对

编辑: @CharlesDuffy指出了我遗漏的另一个问题:数组定义中的整行也应该有引号,但如果您确实需要$USER周围的内部引号,这将不起作用,请参见下面的示例:

declare -a arr=(
    "-b branch1 --single-branch https://$USER@stash/repo1.git"
    https://"$USER"@stash/rep2.git
)
我在我的本地机器上检查了这个,它似乎工作正常

$ ls
one/  test.sh*

$ ( cd one/ ; git branch )
* another_branch
  master

$ cat test.sh
#!/bin/bash

declare -a arr=(
"-b another_branch --single-branch one two"
)

for i in "${arr[@]}"
do
        git clone $i
done

$ ls
one/  test.sh*

$ ./test.sh
Cloning into 'two'...
done.

$ ls
one/  test.sh*  two/

$ ( cd two/ ; git branch )
* another_branch

$
编辑2: 只有当您可以安全地省略$USER周围的内部引号时,这才有效。如果需要,应该在for循环中使用eval,并在数组声明中引用内部引号

$ cat ./test.sh
#!/bin/bash

USER="username containing spaces"   # just for example!

git () {
        echo "$5"
}

declare -a arr=(
"-b branch1 --single-branch https://\"$USER\"@stash/repo1.git"
)

for i in "${arr[@]}"
do
        printf "without eval:\t"
        git clone $i
        printf "with eval:\t"
        eval "git clone $i"
done


$ ./test.sh
without eval:   https://"username
with eval:      https://username containing spaces@stash/repo1.git

这是@charlesduff在我的回答中发现的另一个错误。谢谢Charles,我从你指出的问题中学到了很多

告诉我们你试过什么,告诉我们哪里出了问题。告诉我们您希望它做什么。在第二个数组中,第一个元素是just-b,第二个元素是branch1,等等。即使您将其设置为git clone$i,第二个数组中的第一个值也是just-b,而不是-b branch1-单分支https://$USER@stash/repo1.git。因此,建议的更改打破了最佳实践,即编写依赖字符串拆分的代码比任何其他单一实践都要负责更多的条目,并且如果没有答案中未给出的其他更改,实际上无法解决OP的问题。@charlesduff True,我错过了作者在数组元素周围也没有引号的说法。我将把它添加到我的答案中。分词会导致很多问题,因为它经常被无意中错误地使用。在这里,我故意使用了这个特殊的功能,并且知道我在做什么。除非使用eval,否则引用的内部引号不会被视为语法-因为这段代码目前已经实现,它们将作为文本数据传递给git,因为未引用的扩展只执行字符串拆分和全局扩展,并且不执行报价删除。对于${arr[@]}中的i;评估git克隆$i;不过,这样做可以奏效。对于给定的特定数据,不带引号的扩展是安全的,但是不难想出一个例子,使用不带引号的扩展生成eval的参数列表会破坏一切。谢谢,Charles!我把它加到了答案上。