Python 包含单引号的变量将消失

Python 包含单引号的变量将消失,python,bash,pip,Python,Bash,Pip,我有一个脚本,可以驱动许多软件包的安装。在一个地方,它使用pip。其中一个包需要它自己的特殊命令行参数用于构建过程 pip允许将安装选项传递到生成过程,如下所示: pip安装-U--timeout 30$options--install option='--hdf5=/usr/local/hdf5'表 --安装选项是pip的一个参数。设置为-hdf5=/usr/local/hdf5的值将传递给构建进程。因此,单引号必须存在,以便将所有文本分组为一个等号后面的参数。您可能会说,我可以使用双引号来包

我有一个脚本,可以驱动许多软件包的安装。在一个地方,它使用pip。其中一个包需要它自己的特殊命令行参数用于构建过程

pip允许将安装选项传递到生成过程,如下所示:

pip安装-U--timeout 30$options--install option='--hdf5=/usr/local/hdf5'表

--安装选项是pip的一个参数。设置为-hdf5=/usr/local/hdf5的值将传递给构建进程。因此,单引号必须存在,以便将所有文本分组为一个等号后面的参数。您可能会说,我可以使用双引号来包围安装选项的值。嗯,在命令行我可以

但是,这是增加的复杂性。这是一个脚本。pip命令的参数值传递给数组中的函数。此包的数组项如下所示:
(“表,pip,,--install option='--hdf5=/usr/local/hdf5')

接收函数使用以下片段中的set解析数组项:

IFS=","  # to split apart the pkg array entries

for pkg in "${pkglist[@]}"; do
    set -- ${pkg} 
    if [[ "$2" == "pip" ]]; then  # $1 is pkg, $2 is pip, $3 is url, $4 is options
        DoPip $1 $3 $4
    ...
因此,对于这个包,DoPip将看到:DoPip表“”--install option='--hdf5=/usr/local/hdf5'

问题发生在DoPip中。当我需要运行pip时,我不知道如何扩展最后一个参数。我已经做了一系列调试,看看会发生什么。发生的情况是,3美元的价值只是被放弃了——它就消失了。它将以字符串形式回显,但不会作为命令的一部分工作

查看函数DoPip。为了帮助调试,我将参数重新分配给显式变量。这是没有必要的,但有助于确保我没有犯愚蠢的错误

DoPip() {

 # run pip command to install packages
    # arguments: 1: package-name 2: optional source <URL>
    #            3: optional pip options
    pkgname=$1
    url=$2
    options=$3
输出看起来应该正常工作:

  • 入站参数为:tables--install option='--hdf5=/usr/local/hdf5'
  • 以下是实际使用以下参数运行pip的语句:

    echo "1. The inbound arguments are: $pkgname $url $options"
    
     pip install -U --timeout 30 $options $source
    
    启用调试后,Bash实际看到并运行的是:

    + pip install -U --timeout 30 tables
    
    哇!美元期权怎么了?它不见了!事实上,在这条语句之前,我重复了echo,以验证脚本中没有任何中间部分导致值被刷新。没问题。我可以在之前立即回应$options的价值——没关系。然后,它就消失了

    我不知道发生了什么或者怎么做。我尝试了各种方法来转义数组中的单引号,其中字符串文字最初是基于读取非常特殊的单引号而创建的。什么都不管用。整个变量展开就这样消失了

    我尝试了各种方式进行扩展:

    pip install -U --timeout 30 "$options" $source
    
    那不行。选项中的字符串出现,但被单引号包围,因此pip命令会抛出错误。接下来,我尝试:

    pip install -=U --timeout 30 "${options}" $source
    
    也失败了:单引号和大括号出现了,皮普又不高兴了

    --install options参数至关重要。没有它,构建就会失败

    一定有办法做到这一点。有什么建议吗

    $ bash -version
    GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)
    Copyright (C) 2011 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    

    忽略这些错误,我看到$options的值被正确读取并传递给shell。

    所有这些都嵌入到一个非常大的脚本中。我创建了一个简短的版本来关注这个问题。最后,我采用了一种不同的方法,它依赖于环境变量HDF5_DIR,而不是pip的cmd行开关

    显然,你只能做其中一个。在任何情况下,在清理后的代码中都传递了参数,但如果存在环境变量,则这是一个错误。算了吧

    如果有人感兴趣,我有较短的代码


    当头撞得太重时,离墙远一点,找另一个方法。我将此函数称为closed。

    python包表(又名potables)的安装程序使用提供给pip的构建开关或在开始构建之前设置环境变量来查找hdf5库。在bash脚本中,在开始构建表之前立即创建环境变量更容易/更可靠。没有必要把它放在bash_配置文件中。环境变量只需要存在于构建表的shell中。一旦安装了表,就不再需要环境变量了

    在这个代码片段中,pkglist是一个要安装的模块数组,InstallPackages是一个函数,它遍历数组并调用适当的安装程序:在本例中为pip

        if [[ "$hdf5exists" == "True" ]]; then
            # assert hdf libraries installed
            export HDF5_DIR=/usr/local/hdf5
            pkglist=("${hdf5_pkglist[@]}")  # only install Python wrappers for hdf5
            InstallPackages
        fi
    

    这就是我采用的解决方案。

    谢谢。应该这么简单,但事实并非如此。是否可以使用IFS=“,”将数组项拆分为参数?我甚至不能将echo$options>>作为空行返回。但是,echo“sometext$source$options”是有效的。我完全不知所措。浪费时间!更让人感到奇怪的是。我必须连续有3个变量展开才能展开$options。echo“some text$source$options”不起作用。echo“some text$source$url$options”确实有效。哇!更奇怪的是,echo语句中的扩展顺序被忽略了!echo“1.入站参数是:$options$pkgname$url”和echo“2.入站参数是:$pkgname$url$options”,这两个参数都会生成输出,其中$pkgname首先出现,然后是$option。请注意,$url在这两种情况下的值都是空字符串。这简直是疯了。两个echo语句的输出顺序告诉了我一些事情。我查看了两个函数传递的入站参数。Bash没有“看到”空白参数——它们不在那里。因此,实际的选项字符串进入了$url变量。由于使用数组来传递4个段,因此我在如何将空白字符串作为参数方面仍然存在一些问题。但是,这不再是bash变量的扩展问题了。现在我们正在取得进展。解决了数组问题:将空白项设置为“无”。接收函数得到一个arg值none,我测试它。丑陋,但足够清晰。
        if [[ "$hdf5exists" == "True" ]]; then
            # assert hdf libraries installed
            export HDF5_DIR=/usr/local/hdf5
            pkglist=("${hdf5_pkglist[@]}")  # only install Python wrappers for hdf5
            InstallPackages
        fi