帮助处理变量和换行,并在bash脚本中引用

时间:2010-06-07 16:27:47

标签: bash shell quotes

我想自动执行以下svn命令。注意此命令在我的系统上生成所需的结果 - Ubuntu 10.04,svn 1.6.6,bash shell,当从命令行发出时:

svn ci -m $'Added new File: newFile.txt\nOrig loc: /etc/networking/newFile.txt' /home/user/svnDir/newFile.txt

我想在bash脚本中运行该命令,假设文件的原始完整路径包含在变量$ oFileFull中,文件名在$ oFileName中。该脚本从svn目录执行。我需要考虑文件名和/或路径包含空格的可能性。

因此我的shel脚本中的行可能如下所示:

svn ci -m$'Added new file: ${oFileName}\nOrig loc: ${oFileFull}' ${oFileName}

但我希望在执行命令之前扩展变量(可能包含空格),并且我无法弄清楚如何将svn注释用单引号括起来,这是为了获取新行所必需的颠覆评论日志。我正在试着弄清楚如何正确引用和组装这个命令。任何帮助赞赏。

4 个答案:

答案 0 :(得分:7)

@Scott,我知道这已经得到了解答,但是这里有一些关于echo $ msg和echo“$ msg”之间差异的补充问题的评论。你的例子:

nl=$'\n'
msg="Line 1${nl}Line 2"
echo $msg        # ouput = Line 1 Line 2
echo -e $msg     # ouput = Line 1 Line 2
echo "$msg"      # output = Line 1
                 # Line 2

在每种情况下,知道shell传递给echo命令的参数数量确实很有帮助。 Echo采用了许多论点。它按顺序将它们全部写入标准输出,除了最后一个之外,每个空格后面都有一个空格。

在第一个示例中,echo $ msg,shell将$ msg替换为您设置的字符(其中一个是换行符)。然后在调用echo 之前,它使用内部字段分隔符(IFS)将该字符串拆分为多个参数,并将结果的参数列表传递给echo。默认情况下,IFS设置为空格(空格,制表符和换行符),因此shell会将$ msg字符串切换为四个参数:“Line”,“1”,“Line”和“2”。 Echo甚至从未看过换行符,因为shell认为它是一个分隔符,就像一个空格。

在第二个例子中,echo -e $ msg,echo命令接收五个参数:“ - e”,“Line”,“1”,“Line”,“2”。 -e参数告诉命令扩展它在参数中看到的任何反斜杠字符,但是没有,所以echo保持参数不变。结果与第一个示例相同。

在最后一个示例中,echo“$ msg”,您告诉shell展开$msg并将其内容传递给echo 以将双引号之间的所有内容视为一个参数,所以echo接收一个参数,一个包含字母,数字,空格和换行符的字符串。它完全按照收到它的方式回显该字符串,因此“第1行”和“第2行”出现在不同的行上。

尝试此实验:将IFS设置为任意字符,如字母i,并观察外壳如何以不同方式分割字符串:

nl=$'\n'
msg="Line 1${nl}Line 2"
IFS=i
echo $msg        # ouput = L ne 1
                 # L ne 2

关于空白没什么特别神奇的。在这里,由于奇怪的IFS,shell将字母i视为分隔符,而不是空格或换行符。所以echo接收三个参数:“L”,“ne \ nL”和“ne 2”。 (我将换行符显示为\ n,但它实际上只是一个字符,如X或p或5。)

一旦你意识到shell的命令行上的单引号和双引号都是关于构造命令的参数,逻辑开始变得有意义。

答案 1 :(得分:5)

将换行符放在变量中,在需要换行符的地方使用变量,并将较大字符串周围的引号更改为双引号。您还应始终引用包含文件名的任何变量。

nl=$'\n'
svn ci -m"Added new file: ${oFileName}${nl}Orig loc: ${oFileFull}" "${oFileName}"

答案 2 :(得分:0)

@Dennis:

哇,这很难绕过我的脑袋,如果有人能指出我的网上资源能够清晰简洁地解释这一点,我会很高兴。我找到的那些还没有为我清理它。

我最近的混淆来源如下:

#!/bin/bash
nl=$'\n'
msg="Line 1${nl}Line 2"
echo $msg        # ouput = Line 1 Line 2
echo -e $msg     # ouput = Line 1 Line 2
echo "$msg"      # output = Line 1
                 # Line 2

我试图说明的是,在变量$ msg周围使用双引号将输出分成两行,没有双引号,即使使用-e开关,也没有换行。

我不明白为什么双引号是必要的 - 为什么$ nl变量在被指定为msg变量的一部分时不会扩展?

我希望通过回答我自己的问题,我不会犯下StackOverflow的失礼。事实上,我并没有真正提供答案,而只是回应你的评论。我无法根据需要格式化评论。

答案 3 :(得分:0)

Bash将连接相邻的引用部分。例如,

$ r=rooty
$ t=tooty
$ echo $r$'\n'$t
rooty
tooty
$ echo "$r $r"$'\n'$t
rooty rooty
tooty

对于在线指南,高级bash脚本编写指南可能很有用,但它可能不仅仅是阅读bash的详细手册。我建议使用vim的Man命令(7.2版本的标准,如果不是早期版本)来调出bash手册,然后使用基于缩进的折叠,以便您可以浏览其层次结构。好吧,假设你没有时间和耐心从头到尾阅读所有3300行。