shell 基础

echo $str    与  echo  “$str” 的不同:

cmd $a  与 cmd “$a” 的不同:

如果$a=”a b”; 即:包含空格

前者: cmd接到的是2个参数

后者: cmd接到的是1个参数

举个栗子:如下图,我要把grep的那个关键字用变量替换:

  1. 直接 grep $keywords 测试是不行的,相当于grep 接收了两个参数
  2. 于是乎考虑拼凑第一条命令,就是把单引号拼上:
    grep ‘$kerwords’ 显然是不行的,因为单引号里面的变量是不被替换的
    grep “‘$keywords'” 似乎很完美了,不仅能替换变量,还能添加单引号;上图来看,结果没符合预期,且看下面测试:

    显然,这里的单引号参数值的一部分,而上图第一行的单引号仅仅是在形式化一个参数,是在解释阶段被处理的,至于是单引号还是双引号都关系不大;本质上,我们要保证的是替换后的变量要作为一个(而不是多个)参数传递给grep;从上面我们分析的 $a 和 “$a”的区别,我们便可以知道,其实直接grep “$keyword”就可以了
  3. 总结: 很多情况下,我们是要注意$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

参考资料: http://stackoverflow.com/questions/13763942/bash-why-piping-input-to-read-only-works-when-fed-into-while-read-const

搜索: 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

加入对话

1条评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据