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


91

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

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

但是我无法正确地扩展COLUMNS环境变量的语法。

我尝试了以下各种形式:

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"

有什么建议吗?


那么这些例子对您的情况产生了什么?您想让他们生产什么?

脚本外的命令是否有效?
dfa

您是否尝试过svn diff $@ --diff-cmd /usr/bin/diff -x "-y -w -p -W ""$COLUMNS"
陈千2015年

顺便说一句,使用$@unquoted使其与$*- 完全相同,也就是说,它"foo bar"分为两个独立的参数,foobar。如果您想要保留原始参数列表的原样,则需要"$@"
Charles Duffy

Answers:


16

如果不确定,您可能会在终端上使用“ cols”请求,而忘记了COLUMNS:

COLS=$(tput cols)

无论出于何种原因,这都是我能够从此页面开始工作的唯一解决方案(截至美国东部时间11月5日10:38)。谢谢
杰米

397

对于所有通过Google来这里寻找标题中提出的一般问题的答案的人,请给我一个简短的注释/摘要。以下任何一种方法都可以访问引号内的shell变量:

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

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

将字符括在单引号(')中可保留引号内每个字符的字面值。即使在单引号前加反斜杠,也不能在单引号之间引起单引号。[...]在双引号字符内附(")保留了引号中的所有字符的字面意义,例外$`\,和,启用了历史扩展的时候,!。字符$和`在双引号中保留其特殊含义(请参见Shell Expansions)。反斜杠后跟当由下列字符只保留它的特殊含义:$`"\或换行符。在双引号中,将删除反斜杠,后跟这些字符之一。没有特殊含义的反斜杠前面的字符将保持不变。通过在双引号前面加上反斜杠,可以在双引号内将双引号引起来。如果启用,将执行历史记录扩展,除非!使用反斜杠将双引号引起来。之前的反斜杠!未删除。特殊参数*@在双引号中具有特殊含义(请参见Shell参数扩展)。

在问题的特定情况下,$ COLUMNS是具有非标准属性的特殊变量(请参见上面的lhunath答案)。


20
在单引号的情况下,此解决方法可能会有所帮助:( 'before'"$variable"'after'如该答案所述:stackoverflow.com/a/13802438/2254346
MakisH,2016年

好答案!我在引用单引号内的env变量时遇到了同样的问题。一旦我将单引号改为双引号,我的env变量将按预期进行扩展。
Binita Bharati

14

请注意COLUMNS是:

  1. 不是环境变量。它是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;-))


感谢您的信息; 知道发生了什么事会给人们带来宣泄的感觉。
杰米

2

以下脚本适用于多个值$COLUMNS。我想知道您是否COLUMNS在通话之前没有设置?

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

您可以$COLUMNS在脚本内部回显以查看其设置是否正确吗?


嘘,他的回复:未加引号$@-将单个参数"two words"分成两个单独的参数,twowords。应该"$@"完全按照给定的方式传递参数列表。
Charles Duffy

0

您做得对,所以我想还有其他问题(不是导出COLUMNS吗?)。

调试这些情况的一个技巧是发出专门的命令(对编程语言专家而言是封闭的)。创建一个名为diff-columns的shell脚本,该脚本执行以下操作:

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

并使用

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

这样,您的代码更清晰易读,并且更具模块化(自上而下的方法),并且您可以分别分别测试差异列代码(自下而上的方法)。


在分叉该过程之前已对命令行进行了解析,因此不导出COLUMNS不会成为问题。
彼得·范德·海登

1
他说自己的代码属于bash脚本的一部分,因此可能是问题所在。
科拉斯·纳哈布
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.