bash shell 脚本中的三重嵌套引号

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21168817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 09:16:46  来源:igfitidea点击:

Triple nested quotations in shell script

linuxstringbashshellnested

提问by Degran

I'm trying to write a shell script that calls another script that then executes a rsync command. The second script should run in its own terminal, so I use a gnome-terminal -e "..."command. One of the parameters of this script is a string containing the parameters that should be given to rsync. I put those into single quotes. Up until here, everything worked fine until one of the rsync parameters was a directory path that contained a space. I tried numerous combinations of ',",\",\' but the script either doesn't run at all or only the first part of the path is taken.

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

Here's a slightly modified version of the code I'm using

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

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'\''' "

Within Backup.shthis command is run

Backup.sh此命令中运行

rsync  "$path"

where the destination $pathis calculated from text in Stamp.

其中目的地$path是根据Stamp.

How can I achieve these three levels of nested quotations?

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

These are some question I looked at just now (I've tried other sources earlier as well)

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

I was unsuccessful in applying the solutions to my problem.

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

采纳答案by Sir Athos

Here is an example. caller.shuses gnome-terminalto execute foo.sh, which in turn prints all the arguments and then calls rsyncwith the first argument.

这是一个例子。caller.sh用于gnome-terminalexecute foo.sh,它依次打印所有参数,然后rsync使用第一个参数调用。

caller.sh:

来电者.sh

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

foo.sh:

foo.sh:

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

Edit:If $1contains several parameters to rsync, some of which are long paths, the above won't work, since bash either passes "$1"as one parameter, or $1as multiple parameters, splitting it without regard to contained quotes.

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

There is (at least) one workaround, you can trick bash as follows:

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

caller2.sh:

caller2.sh:

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

foo2.sh:

foo2.sh

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

This will do the equivalent of typing rsync --option1 --option2 "long path"on the command line.

这将相当于rsync --option1 --option2 "long path"在命令行上键入。

WARNING: This hack introduces a security vulnerability, $1can be crafted to execute multiple commands if the user has any influence whatsoever over the string content (e.g. '--option1 --option2 \"long path\"; echo YOU HAVE BEEN OWNED'will run rsyncand then executethe echocommand).

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

回答by JimR

Did you try escaping the space in the path with "\ " (no quotes)?

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

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''' "

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''' "