如何在 Bash 中使用引用字符串中的环境变量

我在 bash 脚本中尝试了以下各种形式:

#!/bin/bash
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

但是我无法正确地使用语法来展开 ABc0环境变量。

我尝试了以下各种形式:

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W $COLUMNS'

还有

svn diff $@ --diff-cmd /usr/bin/diff -x '-y -w -p -W ${COLUMNS}'

还有

eval svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

有什么建议吗?

230358 次浏览

下面的脚本适用于 $COLUMNS的多个值。我想知道如果你没有设置 COLUMNS之前,这个呼叫?

#!/bin/bash
COLUMNS=30
svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W $COLUMNS"

您能在脚本中回显 $COLUMNS以查看它是否设置正确吗?

您的做法是正确的,所以我猜是其他方面的问题(不是导出列?)。

调试这些情况的一个技巧是使用一个专门的命令(编程语言人员的一个闭包)。创建一个名为 diff-column 的 shell 脚本:

exec /usr/bin/diff -x -y -w -p -W "$COLUMNS" "$@"

只是利用

svn diff "$@" --diff-cmd  diff-columns

通过这种方式,您的代码更容易阅读,也更模块化(自顶向下方法) ,并且您可以完全独立地测试 diff-column 代码(自底向上方法)。

如果不确定,您可以在终端上使用“ protocol”请求,然后忘记列:

COLS=$(tput cols)

请注意,COLUMNS是:

  1. NOT 一个环境变量,它是一个由 bash 自己设置的普通 bash 参数。
  2. 接收到 SIGWINCH信号后自动设置。

第二点通常意味着您的 COLUMNS变量将只在您的 互动 shell 中设置,而在 bash 脚本中设置 没有

如果脚本的 stdin连接到终端,你可以通过询问终端手动查找终端的宽度:

tput cols

为了在您的 SVN 命令中使用它:

svn diff "$@" --diff-cmd /usr/bin/diff -x "-y -w -p -W $(tput cols)"

(注意: 你应该 引用 "$@"和远离 eval; ——)

对于那些通过谷歌来寻找标题中一般问题的答案的人来说,这只是一个简短的注释/摘要。以下任何一种方法都可以用来访问引号中的 shell 变量:

echo "$VARIABLE"
echo "${VARIABLE}"

使用单引号是主要问题。根据 Bash 参考手册:

在单引号中包含字符(')会保留引号中每个字符的字面值。单引号可能不会出现在单引号之间,即使前面有反斜杠也是如此。 [...] 用双引号括起的字符(")保留引号中所有字符的字面值,但 $`\和启用历史展开时的 !除外。字符 $和‘在双引号中保留它们的特殊含义(参见 Shell 扩展)。反斜杠只有在后跟以下字符之一时才保留其特殊含义: $`"\或换行符。在双引号内,移除后跟这些字符之一的反斜杠。没有特殊含义的字符前面的反斜杠不会被修改。双引号可以在双引号前加反斜杠引用。如果启用,将执行历史展开,除非使用反斜杠转义出现在双引号中的 !!前面的反斜杠没有被删除。 特殊参数 *@在双引号中具有特殊意义(参见 Shell 参数展开)。

在问题中提到的特定情况下,$COLUMNS 是一个具有非标准属性的特殊变量(参见上面 Lhunath 的回答)。