这里有一系列情况,其中echo$var
可以显示与刚刚分配的值不同的值。无论分配的值是“双引号”、“单引号”还是未引号,都会发生这种情况。
如何让 shell 正确设置我的变量?
星号
预期的输出是/*Foobar是免费软件*/
,但我得到了一个文件名列表:
$ var="/* Foobar is free software */"
$ echo $var
/bin /boot /dev /etc /home /initrd.img /lib /lib64 /media /mnt /opt /proc ...
方括号
期望值是< code>[a-z],但有时我得到的是一个字母!
$ var=[a-z]
$ echo $var
c
换行符(换行符)
预期值是一个单独行的列表,但所有值都在一行上!
$ cat file
foo
bar
baz
$ var=$(cat file)
$ echo $var
foo bar baz
多个空格
我期望一个仔细对齐的表格标题,但相反,多个空格要么消失,要么折叠成一个!
$ var=" title | count"
$ echo $var
title | count
标签
我期望两个制表符分隔的值,但相反,我得到了两个空格分隔的值!
$ var=$'key\tvalue'
$ echo $var
key value
除了未引用导致的其他问题外,< code>-n和< code>-e可以被< code>echo用作参数。(根据< code>echo的POSIX规范,只有前者是合法的,但是有几个常见的实现违反了规范并消耗了< code>-e。
为了避免这种情况,当细节很重要时,请使用printf
而不是echo
。
因此:
$ vars="-e -n -a"
$ echo $vars # breaks because -e and -n can be treated as arguments to echo
-a
$ echo "$vars"
-e -n -a
但是,使用 echo 时,正确的引用并不总是能为您节省成本
:
$ vars="-n"
$ echo "$vars"
$ ## not even an empty line was printed
…而它会用printf
保存您:
$ vars="-n"
$ printf '%s\n' "$vars"
-n
您可能想知道为什么会发生这种情况。结合其他人的精彩解释,找到Gilles在Unix中编写的为什么我的外壳脚本会被空格或其他特殊字符阻塞?的参考资料
< code>$foo并不意味着“取变量< code>foo的值”。它意味着更复杂的东西:
foo*bar
则此步骤的结果是3元素列表foo
、*
、bar
foo
的列表,然后是当前目录中的文件列表,最后是bar
。如果当前目录为空,则结果为foo
、*
、bar
请注意,结果是字符串列表。shell 语法中有两个上下文:列表上下文和字符串上下文。字段拆分和文件名生成仅在列表上下文中发生,但大多数情况下都是如此。双引号分隔字符串上下文:整个双引号字符串是单个字符串,不可拆分。(例外:“$@”
扩展到位置参数列表,例如,如果有三个位置参数,则“$@”
等效于“$1”“$2”“$3”
。请参阅 $* 和 $@之间有什么区别?
用$(foo)
或'foo'
替换命令也是如此。顺便说一句,不要使用'foo'
:它的引用规则很奇怪且不可移植,所有现代shell都支持$(foo)
,这是绝对等价的,除了有直观的引用规则。
算术替换的输出也经历了相同的扩展,但这通常不是问题,因为它只包含不可扩展的字符(假设IFS
不包含数字或-
)。
请参阅何时需要双引号?有关可以省略引号的情况的更多详细信息。
除非您的意思是让所有这些繁琐的事情发生,否则请记住始终在变量和命令替换之间使用双引号。注意:省略引号不仅会导致错误,还会导致安全漏洞。
在上面的所有情况下,变量都设置正确,但没有正确读取!正确的方法是在引用时使用双引号:
echo "$var"
这给出了所有示例中的预期值。总是引用变量引用!
为什么?
当变量未被引用时,它将:
>
进行字段拆分,其中值在空格上拆分为多个单词(默认情况下):
之前: /* 福吧是自由软件 */
之后: /*
, 福巴
, 是
, 免费
, 软件
, */
这些单词中的每一个都将经历路径名扩展,其中模式被扩展为匹配的文件:
之前:< code>/*
之后:< code>/bin,< code>/boot,< code>/dev,< code>/etc,< code>/home,...
最后,所有的参数都被传递给echo,它将它们写出,用单个空格分隔,给出
/bin /boot /dev /etc /home Foobar is free software Desktop/ Downloads/
而不是变量的值。
当变量被引用时,它将:
这就是为什么您应该始终引用所有变量引用,除非您特别需要单词拆分和路径名扩展。shellcheck等工具可以提供帮助,并会警告上述所有情况下缺少引号。
问题内容: 有谁知道如何修理它。我正在使用Mac OS 10.8.2 问题答案: 在Python 3中是一个函数;它应该是: 正确安装或使用新版本(如果存在错误)。 在Python 3.3上工作正常。
致命错误:Uncaught ArgumentCounter错误:array_merge()不接受C:\xampp\htdocs\wp includes\widgets中的未知命名参数。php:1265堆栈跟踪:#0 C:\xampp\htdocs\wp includes\widgets.php(1265):array_merge(wp_inactive_widgets:array,sidebar-
我刚刚从Windows 8升级到Windows 10(都是64位),我之前的带有用于Android开发的ADT插件的Eclipse Juno不再启动。 我所能看到的只是鼠标指针显示某些内容正在加载几秒钟,然后没有其他反应。 我所尝试的 < li >重命名< code>eclipse.ini以让它重新创建它:甚至没有重新创建它,所以将其重新命名。 < li >在Eclipse exe上打开了“Win
问题内容: 我只是运行了一个简单的MySQL CREATE TABLE语句,该语句产生了这一行 “查询确定,受影响的行为0,警告为1(0.07秒)。” 但是,它实际上并没有告诉我警告是什么。您如何查看刚刚发生的警告的内容?我正在使用MySQL 5.1,如果有帮助的话。我在网上唯一发现的是“ SHOW WARNINGS;但这只会产生 “空集(0.00秒)。” 问题答案: 是我知道的唯一方法,但是必须
失败:生成失败,出现异常。 出了什么问题:任务'执行失败:app: check DebugAarMetadata'。 发生多个任务操作失败:执行com时发生故障。Android建筑格雷德尔。内部的任务。CheckAarMetadataWorkAction
mvn清洁安装建筑故障 爪哇 似乎环境没有问题。那么,导致构建失败的问题在哪里呢?