echo $str 与 echo “$str” 的不同:
1 2 3 4 5 6 |
[phpor@net ~]$ str=`echo -e "A\nB"` [phpor@net ~]$ echo $str A B [phpor@net ~]$ echo "$str" A B |
cmd $a 与 cmd “$a” 的不同:
如果$a=”a b”; 即:包含空格
前者: cmd接到的是2个参数
后者: cmd接到的是1个参数
举个栗子:如下图,我要把grep的那个关键字用变量替换:
- 直接 grep $keywords 测试是不行的,相当于grep 接收了两个参数
- 于是乎考虑拼凑第一条命令,就是把单引号拼上:
grep ‘$kerwords’ 显然是不行的,因为单引号里面的变量是不被替换的
grep “‘$keywords'” 似乎很完美了,不仅能替换变量,还能添加单引号;上图来看,结果没符合预期,且看下面测试:
显然,这里的单引号参数值的一部分,而上图第一行的单引号仅仅是在形式化一个参数,是在解释阶段被处理的,至于是单引号还是双引号都关系不大;本质上,我们要保证的是替换后的变量要作为一个(而不是多个)参数传递给grep;从上面我们分析的 $a 和 “$a”的区别,我们便可以知道,其实直接grep “$keyword”就可以了 - 总结: 很多情况下,我们是要注意$var 最好写成 “$var” 的;我们经常想要的是 “$var” ,而不是 $var
cmd $a $b 与 cmd “$a” “$b”
前者如果$a为空,则 $1得到的将是$b的值,出现参数错位的情况;后者则不会出现这种情况
管道到read
a b 变量没有被成功赋值;
原因: 由于管道的存在,默认情况下,第一个管道的前面部分是在当前bash进程中执行的,后面的被管道隔开的命令都是在单独的子shell中执行的,那么是bash的内置命令(如:read)也要单启动一个bash进程来执行,而子进程中的变量不会对父进程产生影响,显然,例子中read a b里面的a b是子进程中的变量,在父进程中是不能echo出来的。
据说bash提供了一个选项lastpipe
,可以改变bash的行为,使得管道链中的最后一个命令在当前bash中执行,其他的命令都在子shell中执行,不过我的bash目前是4.1(目前最新是4.4,还没stable),还没有这个选项,通过shopt查询是否有该选项。不过,据说使用该选项将不得不禁用作业控制。
还有其他办法:
办法1: 使用Here Document
办法二: 使用Here String
办法三: 使用Here Command
这个似乎应该叫做Process Substitution
参考: http://www.tldp.org/LDP/abs/html/process-sub.html
搜索: https://www.google.com.hk/?gws_rd=cr,ssl#safe=strict&q=bash+read+pipe+into+variable
关于here document、here string
here文档和here字符串不同于其他语言中仅仅用来定义复杂的字符串的,而是有特殊目的的,bash中的here文档和here字符串是用在命令后面的,他自动修改了命令的标准输入,如:
错误用法:
我们发现 变量a没有被成功复制。
hello world也没有成功被打印出来。
正确的用法:
等效于:
《Advanced Bash-Scripting Guide》中是这么说的:
A here document is a special-purpose code block. It uses a form of I/O redirection to feed a command list to an interactive program or a command, such as ftp, cat, or the ex text editor.
参考资料: http://www.tldp.org/LDP/abs/html/here-docs.html
关于 Here command
没有找见这方面的文档
关于字面量
对于 echo “$a” 大可不必担心 $a 有函数 双引号而在替换后破坏结构;如果a='”123′ , 则不必担心echo “$a” 会被处理成 echo “”123”
关于花括号扩展
花括号与元素之间不能有空格,元素之间逗号分隔且不能有空格
如果花括号中的元素含有变量,而变量中含有空格是没有问题的,但是空格元素可能会被丢掉,所以,为了不发生意外,变量最好用双引号引起来
$* vs $@
参考: http://c.biancheng.net/cpp/view/2739.html
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
echo {a,b,c} 中不能有空格的原因是:如果有了空格就相当于多个参数了