【问题标题】:Triple nested quotations in shell scriptshell脚本中的三重嵌套引号
【发布时间】:2014-02-05 18:36:15
【问题描述】:

我正在尝试编写一个 shell 脚本,该脚本调用另一个脚本,然后执行 rsync 命令。 第二个脚本应该在它自己的终端中运行,所以我使用gnome-terminal -e "..." 命令。此脚本的参数之一是一个字符串,其中包含应提供给 rsync 的参数。我把它们放在单引号中。 直到这里,一切正常,直到 rsync 参数之一是包含空格的目录路径。我尝试了许多 ',",\",\' 的组合,但脚本要么根本不运行,要么只使用路径的第一部分。

这是我正在使用的代码的略微修改版本

gnome-terminal -t 'Rsync scheduled backup' -e "nice -10 /Scripts/BackupScript/Backup.sh 0 0 '/Scripts/BackupScript/Stamp' '/Scripts/BackupScript/test' '--dry-run -g -o -p -t -R -u --inplace --delete -r -l '\''/media/MyAndroid/Internal storage'\''' "

Backup.sh 内运行此命令

rsync $5 "$path"

目标$path 是根据Stamp 中的文本计算得出的。

如何实现这三层嵌套引用?

这些是我刚才看到的一些问题(我之前也尝试过其他来源)

我未能成功地将解决方案应用于我的问题。

【问题讨论】:

    标签: linux string bash shell nested


    【解决方案1】:

    这是一个例子。 caller.sh 使用gnome-terminal 执行foo.sh,然后打印所有参数,然后使用第一个参数调用rsync

    caller.sh

    #!/bin/bash
    gnome-terminal -t "TEST" -e "./foo.sh 'long path' arg2 arg3"
    

    foo.sh:

    #!/bin/bash
    echo $# arguments
    for i; do    # same as: for i in "$@"; do
        echo "$i"
    done
    rsync "$1" "some other path"
    

    编辑:如果$1 包含多个rsync 参数,其中一些是长路径,以上将不起作用,因为bash 要么将"$1" 作为一个参数传递,要么将@987654329 @ 作为多个参数,将其拆分而不考虑包含的引号。

    有(至少)一种解决方法,您可以按如下方式欺骗 bash:

    caller2.sh

    #!/bin/bash
    gnome-terminal -t "TEST" -e "./foo.sh '--option1 --option2 \"long path\"' arg2 arg3"
    

    foo2.sh

    #!/bin/bash
    rsync_command="rsync $1"
    eval "$rsync_command"
    

    这相当于在命令行输入rsync --option1 --option2 "long path"

    警告:此 hack 引入了一个安全漏洞,如果用户对字符串内容有任何影响,$1 可以被设计为执行多个命令(例如,'--option1 --option2 \"long path\"; echo YOU HAVE BEEN OWNED' 将运行 rsync然后执行echo 命令)。

    【讨论】:

    • Nit: in "$@" 是多余的。
    • @l0b0:请详细说明,有没有更简单的语法?
    • 删除它。 for foo 将循环遍历 "$@" 而无需任何额外的语法。语法糖。
    • 这确实是一个非常相似且更易于阅读的程序。我现在的问题是 1.'long path' 不仅包含源,还包含其他参数。所以我会使用$1 而不是"$1" 2。源是一个带空格的字符串,所以它需要用引号括起来,这将我们带到了三重嵌套。我可以将源与其他参数分开,让 foo.sh 有 4 个参数,但这不能解决排除问题,例如。
    • 我确实知道 eval 是一种可能性,但我不想使用它。相反,我正在考虑摆脱所有 rsync 参数周围的第二级(单)引号,并简单地将 rsync 从第五个参数开始的所有参数作为数组或其他东西。然后,我可以将长路径用单引号括起来,并使用类似于您的第一种方法的方法。这行得通吗?
    【解决方案2】:

    您是否尝试使用“\”(不带引号)转义路径中的空格?

    gnome-terminal -t 'Rsync scheduled backup' -e "nice -10 /Scripts/BackupScript/Backup.sh 0 0 '/Scripts/BackupScript/Stamp' '/Scripts/BackupScript/test' '--dry-run -g -o -p -t -R -u --inplace --delete -r -l ''/media/MyAndroid/Internal\ storage''' "

    【讨论】:

    • “\”不被视为转义字符,可能与将参数传递给 rsync 时也不考虑引号的原因相同。
    猜你喜欢
    • 2017-09-19
    • 2021-08-21
    • 1970-01-01
    • 2012-05-27
    • 2012-08-20
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    • 2011-04-25
    相关资源
    最近更新 更多