【问题标题】:Nested quotes in BashBash 中的嵌套引号
【发布时间】:2018-05-07 12:38:09
【问题描述】:

请让我用一些示例脚本来解释我的场景,它比我的实际应用程序简单得多,但表现出相同的行为:

对于演示,我使用了两个 bash shell 脚本。第一个叫argtest.sh 简单的输出命令行参数:

#/bin/bash

echo "Argument 1: $1"
echo "Argument 2: $2"

测试:

root@test:~# ./argtest.sh 1 2
Argument 1: 1
Argument 2: 2

root@test:~# ./argtest.sh "1 2" 3
Argument 1: 1 2
Argument 2: 3

这按预期工作

我创建了另一个这样的命令:

./argtest.sh $(for i in ` seq 1 2 ` ; do echo Number $i; done) 

这是结果

Argument 1: Number
Argument 2: 1

我在Number 周围尝试了许多不同的引号 (") 和转义引号 (\") 组合,但没有任何组合产生所需的输出:

Argument 1: Number 1
Argument 2: Number 2

我怎样才能得到那个输出?

【问题讨论】:

    标签: bash shell quotes


    【解决方案1】:

    因为参数会被分词,您可以更改$IFS并将新的分隔符放入您的echo

    IFS=$'_\n'
    ./argtest.sh $(for i in {1..2} ; do echo "Number ${i}_"; done )
    

    别忘了恢复旧的 $IFS

    oIFS=$IFS
    ...
    IFS=$oIFS
    

    btw {1..2} 等同于 seq 1 2 但你不需要外部命令

    【讨论】:

    • 基本上,所有答案都是相似的,对我来说似乎都是正确的(现在,我明白了),但我将此标记为正确答案,因为我使用这种方法解决了我的问题。谢谢!
    【解决方案2】:

    正如 chepner 所提到的,命令替换需要分词。

    下面是几个例子来更好地理解这一点

    以下是我将 echo 替换为 printf 并转义双引号时的行为:-

    for i in ` seq 1 2 ` ; do printf "\"Number %d\" " "$i"; done; printf "\n"
    "Number 1" "Number 2"
    
    ./arg.sh  $(for i in ` seq 1 2 ` ; do printf "\"Number %d\" " "$i"; done; printf "\n")
    Argument 1: "Number                                                                   
    Argument 2: 1"     
    

    现在,如果我尝试将整个命令替换用双引号括起来,它会将它们视为一个参数:-

    ./arg.sh "$(for i in ` seq 1 2 ` ; do printf "\"Number %d\" " "$i"; done; printf "\n")"
    Argument 1: "Number 1" "Number 2"                                                                                                                         
    Argument 2:                                                                                                                                                                      
    

    【讨论】:

      【解决方案3】:

      你不能。命令替换受分词的影响。它的输出是两行

      Number 1
      Number 2
      

      但换行符在分词期间被视为任意空格。因此,命令替换被分成 4 个单词(Number1Number2),每个单词都是 argtest.sh 的单独参数。

      在分词过程中,额外的引号将被逐字处理;像 "a b" c 这样的字符串被分成 3 个单词("ab"c),而不是 2 个单词(a bc)。

      要做你想做的事,你需要使用while循环从你的循环中一次读取一行输出。例如:

      for i in $(seq 1 2); do
        echo "Number $i"
      done | while read -r line; do
        ./argtest.sh "$line"
      done
      

      【讨论】:

        【解决方案4】:

        您可以使用xargs

        for i in ` seq 1 2 ` ; do echo Number $i; done | xargs -d $'\n' ./argtest.sh
        

        【讨论】:

          猜你喜欢
          • 2011-09-30
          • 2013-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-09
          • 2014-11-14
          • 1970-01-01
          • 2012-04-08
          相关资源
          最近更新 更多