今天遇到几个shell脚本的问题,记录一下。
1、之前一直没注意用source执行脚本和直接执行脚本的区别。今天遇到一个问题,在脚本中有exit命令,当用source执行时,不仅会退出脚本,连整个终端都退出了,而直接运行则不会这样。后来查了一下才知道有如下区别:
source命令的功能是使Shell读入指定的Shell程序文件并依次执行文件中的所有语句,通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录。
source命令等价于.符号。source命令其实只是简单地读取脚本里面的语句依次在当前shell里面执行,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面,即脚本中的变量在当前shell可见。说白了就是只有一个会话,这也解释了exit命令会退出整个终端的现象,因为根本就是在当前shell中执行的exit。
当shell脚本具有可执行权限时,用sh filename与./filename执行脚本是没有区别的。./filename是因为当前目录没有在PATH中,"."是用来表示当前目录的。
sh filename 重新建立一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell新建的、改变的变量不会被带回父shell,除非使用export。也就是说脚本是在另一个会话中执行的,exit只是退出了子shell回到了父shell。
2、C风格的for循环
之前看到的for循环都是for val in list这种形式,今天看到了另一种for((i=0;i<10;i++));do done
这个跟c语言基本相同
3、test测试语言中用双方括号
[[是 bash 程序语言的关键字。并不是一个命令,[[ ]] 结构比[ ]结构更加通用。在[[和]]之间所有的字符都不会发生文件名扩展或者单词分割,但是会发生参数扩展和命令替换。
支持字符串的模式匹配,使用=~操作符时甚至支持shell的正则表达式。字符串比较时可以把右边的作为一个模式,而不仅仅是一个字符串,比如[[ hello == hell? ]],结果为真。[[ ]] 中匹配字符串或通配符,不需要引号。
使用[[ ... ]]条件判断结构,而不是[ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
bash把双中括号中的表达式看作一个单独的元素,并返回一个退出状态码。
4、echo内容到一个不存在的文件,如果路径存在则创建该文件,如果路径不存在则报错。
5、shell中利用sqlplus操作数据库
这个需要再看一下,尤其sql语句的的结尾符。
6、看到一个比较奇怪的用法
read a b c d < <(echo "$var")
开始以为是重定向,后来发现错了,小括号空格小括号是用来分割变量,分别赋给前面几个变量。注意格式,不这样写会报错。