代码之家  ›  专栏  ›  技术社区  ›  user5507535

尝试在sh脚本中传递python变量[duplicate]

  •  0
  • user5507535  · 技术社区  · 5 年前

    它的工作原理与广告一致:

    # example 1
    #!/bin/bash
    grep -ir 'hello world' .
    

    这不是:

    # example 2
    #!/bin/bash
    argumentString="-ir 'hello world'"
    grep $argumentString .
    

    尽管 'hello world' 在第二个例子中,grep用引号括起来解释 'hello 作为一个论点 world' 另一方面,也就是说,在这种情况下, '你好 将是搜索模式和 世界 将是搜索路径。

    同样,只有当参数从 argumentString 变量。grep正确解释 '你好世界' 作为第一个例子中的一个参数。

    有人能解释为什么吗?是否有适当的方法来扩展字符串变量,从而保留每个字符的语法,以便由shell命令正确解释?

    0 回复  |  直到 6 年前
        1
  •  32
  •   Jonathan Leffler    6 年前

    为什么?

    当字符串被展开时,它会被拆分成单词,但不会重新计算以查找特殊字符,如引号或美元符号或。。。这是自1978年左右的伯恩壳牌(Bourne shell)以来,壳牌一直“一贯”的做法。

    修复

    bash ,使用数组保存参数:

    argumentArray=(-ir 'hello world')
    grep "${argumentArray[@]}" .
    

    或者,如果勇敢/鲁莽,使用 eval :

    argumentString="-ir 'hello world'"
    eval "grep $argumentString ."
    

    另一方面,谨慎往往是勇敢的最好部分,与 评估 是一个谨慎胜于勇敢的地方。如果你不能完全控制 评估 'd(如果命令字符串中有任何用户输入没有经过严格验证),那么您将面临潜在的严重问题。

    注意,Bash的扩展序列在 Shell Expansions 在GNU Bash手册中。请特别注意第3.5.3节Shell参数扩展、第3.5.7节单词拆分和第3.5.9节引号删除。

        2
  •  5
  •   nneonneo    12 年前

    当您将引号字符放入变量中时,它们只会变成纯文本(请参见 http://mywiki.wooledge.org/BashFAQ/050 ;感谢@tripleee指出此链接)

    相反,请尝试使用数组传递参数:

    argumentString=(-ir 'hello world')
    grep "${argumentString[@]}" .
    
        3
  •  4
  •   markgo2k    7 年前

    在研究这个和相关的问题时,我很惊讶没有人提到使用显式子shell。对于bash和其他现代shell,可以显式地执行命令行。在bash中,它需要-c选项。

    argumentString="-ir 'hello world'"
    bash -c "grep $argumentString ."
    

    完全符合最初提问者的要求。这种技术有两个限制:

    1. 只能在命令或参数字符串中使用单引号。
    2. 只有导出的环境变量才可用于该命令

    此外,此技术还处理重定向和管道,其他外壳也可以工作。您还可以使用bash内部命令以及在命令行中工作的任何其他命令,因为您实际上是要求子shell bash将其直接解释为命令行。这里有一个更复杂的例子,一个有点复杂的l s-l变体。

    cmd="prefix=`pwd` && ls | xargs -n 1 echo \'In $prefix:\'"
    bash -c "$cmd"
    

    我用这种方法和参数数组构建了命令处理器。一般来说,这条路 许多的 更容易编写和调试,而且回显正在执行的命令也很简单。OTOH,param数组在确实有抽象的参数数组时工作得很好,而不是仅仅需要一个简单的命令变量。