如何传递到命令行参数时逃脱bash中的变量 [英] How to escape a variable in bash when passing to command line argument

查看:230
本文介绍了如何传递到命令行参数时逃脱bash中的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个bash脚本(Cygwin的),使用一些Windows路径包含空格。因此,我逃脱,在我的变量定义一个\\的空间。在脚本中的一切工作正常。但是,我需要这个变量作为参数传递到可执行命令行。当我这样做,我的转义得到弄糟。

I've got a bash script (cygwin) that uses some windows paths with spaces in them. Consequently, I have escaped the space with a \ in my variable definition. Everything within the script works fine. However, I need to pass this variable as an argument to command line executable. When I do that, my escaping gets messed up.

样的非功能脚本:

#!/bin/sh                                                                                                                                 

# file paths                                                                                                                              
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"


        # prepare attachments                                                                                                             
        args=""
        for file in $attachments ; do
            file=${file//[ \\n]/}
            touch $file
            mv $file "$destinationPath/$file"
            args="$args -a $destinationPath/$file"
        done

        # send email                                                                                                                      
        echo -e $body | email --from-addr nosender@mydomain.com --from-name "Automated CSS Downloader" --subject "Downloaded new file(s) \
from CSS" $args eric@mydomain.com

从脚本输出:

$ bash -x test.sh
+ destinationPath='/cygdrive/c/Documents and Settings/Eric/My Documents/'
+ attachments='\n2013-12-12.pdf'
+ body='Test Body'
+ recipient=asdf@asdf.com
+ args=
+ for file in '$attachments'
+ file=2013-12-12.pdf
+ touch 2013-12-12.pdf
+ mv 2013-12-12.pdf '/cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf'
mv: listing attributes of `2013-12-12.pdf': Invalid argument
+ args=' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf'
+ echo -e Test Body
+ email --from-addr nosender@mydomain.com --from-name 'Automated CSS Downloader' --subject 'Downloaded new file(s) from CSS' -a /cygdrive/c/Documents and Settings/Eric/My Documents//2013-12-12.pdf eric@mydomain.com
email: WARNING: Email address 'and' is invalid. Skipping...
email: FATAL: Could not open attachment: /cygdrive/c/Documents: No such file or directory

所以,你可以看到在路径中逃脱空间没有被出口在的$ args变量。我假设错误来就行了ARGS = ...。但我不知道如何逃脱的DestinationPath $以确保转义字符将被保留。

So, as you can see the escaped space in the path is not being exported in the $args variable. I am assuming the error comes on the line "args=...". But I am not sure how to escaped $destinationPath to ensure that the escaped characters are retained.

我一直使用双引号(没有逃脱空间)中的DestinationPath但无济于事尝试。如果我尝试在ARGS =行至双引号$的DestinationPath,则输出也得到一切搞砸了一堆额外的报价

I've tried using double quotes (with no escaped space) in destinationPath but to no avail. If I try to double quote $destinationPath in the args= line, then the output also gets all screwed up with a bunch of extra quoting.

我怎样才能得到这个工作?我试着用$ IFS变量玩弄,但我真的不知道我在干嘛用的,似乎并不能得到它与工作,但其中我怀疑的解决方案有事做$ IFS。

How can I get this to work? I've tried playing around with the $IFS variable, but I don't really know what I'm doing with it, and can't seem to get it working with that either, although I suspect the solution has something to do with $IFS.

推荐答案

有这样做没有一个数组没有什么好办法。 (有这样做,使用评估,但数组是简单的没有好办法。)

There's no good way of doing this without an array. (There's a not good way of doing it, using eval, but the array is simpler.)

问题是,你希望每个文件,最终成为一个参数电子邮件,但你要对所有这些论点积聚成一个bash变量。这里还有没有办法做到这一点:你可以让bash的变量插入作为一个参数($ ARG),也可以导致其插入作为然而,许多单词,会分成( $ ARG ),但你不能让它按照拆分是否被创建的变量空间的时候了逃脱的,因为庆典只记得分配给一个变​​量,而不是逃避标记的字符串。

The problem is that you want each file to end up as one argument to email, but you want to accumulate all those arguments into a bash variable. There's just no way to do that: you can cause the bash variable to be inserted as a single argument ("$arg") or you can cause it to be inserted as however many words it gets split into ($arg), but you can't get it to be split according to whether or not spaces were escaped when the variable was created, because the bash only remembers the string assigned to a variable, not the escape marks.

不过,你可以用一个数组做到这一点,因为你可以使每名只有一个数组元素,你可以得到的bash插入一个数组元素每一个参数。

However, you can do it with an array, because you can make every filename exactly one array element, and you can get bash to insert an array as one argument per element.

下面的方式:

# file paths                                                                                                                              
destinationPath="/cygdrive/c/Documents and Settings/Eric/My Documents/"
attachments="\n2013-12-12.pdf"
body="Test Body"
recipient="asdf@asdf.com"


# prepare attachments                                                                                                             
args=()
for file in $attachments ; do
    file=${file//[ \\n]/}
    touch $file
    mv $file "$destinationPath/$file"
    args+=(-a "$destinationPath/$file")
done

# send email                                                                                                                      
echo -e $body |
  email --from-addr nosender@mydomain.com \
        --from-name "Automated CSS Downloader" \
        --subject "Downloaded new file(s) from CSS" \
        "${args[@]}" eric@mydomain.com

您还可能希望在附件变量到一个数组;从换行符的presence,我假设你实际上设置它一些更复杂的方式,所以我并没有改变code。但是,如果附件名称中有一个空间中的当前code将无法正常工作(我pretty确保换行符将在的参数扩展被淘汰的形式,除非你已经改变了 $ IFS 的价值,所以文件= $ {//文件[\\\\ñ ] /} 应当是不必要的。)

You might also want to make the attachments variable into an array; from the presence of the newline character, I'm assuming that you're actually setting it in some more complicated way, so I didn't change the code. But your current code won't work if the attachment name has a space in it (and I'm pretty sure that the newline will be eliminated by the parameter expansion in the for form, unless you've altered the value of $IFS, so file=${file//[ \\n]/} shouldn't be necessary.)

这篇关于如何传递到命令行参数时逃脱bash中的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆