bash - 传递给命令行参数时如何在 Bash 中转义变量

标签 bash variables escaping ifs

我有一个 Bash 脚本 (Cygwin),它使用一些带有空格的 Windows 路径。因此,我在变量定义中用 \ 转义了空格。

脚本中的一切工作正常。但是,我需要将此变量作为参数传递给命令行可执行文件。当我这样做时,我的转义过程变得一团糟。

非功能性脚本示例:

#!/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 以确保保留转义字符。

我试过在 destinationPath 中使用双引号(没有转义空格),但无济于事。如果我尝试在 args= 行中双引号 $destinationPath,那么输出也会被一堆额外的引号搞得一团糟。

我怎样才能让它发挥作用?我试过玩弄 $IFS 变量,但我真的不知道我在用它做什么,而且似乎也无法让它工作,尽管我怀疑解决方案与 $ 有关国际金融中心。

最佳答案

没有数组就没有好的方法。 (有一个不好的方法,使用 eval,但数组更简单。)

问题是您希望每个文件都作为 email 的一个参数结束,但您希望将所有这些参数累积到一个 Bash 变量中。没有办法做到这一点:您可以将 Bash 变量作为单个参数 ("$arg") 插入,或者您可以将它插入,无论它被分成多少个词($arg),但是你不能根据创建变量时是否转义空格来拆分它,因为 Bash 只记住分配给变量的字符串,而不是转义符标记。

但是,您可以使用数组来做到这一点,因为您可以使每个文件名恰好是一个数组元素,并且您可以让 Bash 插入一个数组作为每个元素的一个参数。

方法如下:

# 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

您可能还想将attachments 变量变成一个数组;从换行符的存在来看,我假设您实际上是以更复杂的方式设置它,所以我没有更改代码。但是,如果附件名称中有空格,则您当前的代码将不起作用(我很确定换行符将被 for 形式的参数扩展消除,除非您已经改变了 $IFS 的值,所以 file=${file//[\\n]/> 应该不是必需的。)

关于bash - 传递给命令行参数时如何在 Bash 中转义变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17257388/

相关文章:

bash - grep 如何处理 DOS 行尾?

javascript - JavaScript : assign var in function and use var out that function

java - 如何在 Java 字符串中输入引号?

java - 为什么在 Java Regex 中需要两个斜杠才能找到 "+"符号?

windows - cmd中的计算机名变量

javascript - 如何在 JavaScript/jQuery 中转义字符?

linux - 如何控制 Shell 脚本的输入?

linux - bash sort -g 用于 Ubuntu 14.04LTS 中的 x.xxe+x 格式数字

bash - Bash-从循环中获取基本名称

java - 在 Java 中理解对象并修改其链表中的变量时遇到困难