Shell 编程基础
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shell 编程基础相关的知识,希望对你有一定的参考价值。
Shell脚本的关键在于输入多个命令并处理每个命令的结果,甚至需要将一个命令的结果传给另一个命令。Shell可以让你将多个命令串起来,一次执行完成。
基本格式:
第一行必须为固定格式,指明脚本使用哪种shell来运行脚本,通常shell脚本中会以 # 作为注释,注释号后面的内容不会参与脚本的运行,但是,第一行是个例外。
变量命名法则:
1、不能使程序中的保留字:例如if, for
2、只能使用数字、字母及下划线,且不能以数字开头,不能使用 - (减号)
正确:_abc123 ; abc123 ; abc_123
错误:var1-abc=100 ; var1-123=100 ; -var1=100
3、见名知义
name ,date
4、统一命名规则:驼峰命名法
HostName
直接运行脚本的时候,会新开一个shell进程,脚本中默认关闭了alias功能
局部变量:生效范围为当前shell进程;对当前shell之外的其它shell进程,包括当前shell的子shell进程均无效。
环境(全局)变量:生效范围为当前shell进程及其子进程
本地变量:生效范围为当前shell进程中某代码片断,通常指函数
位置变量:$1, $2,$N ...来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数
特殊变量:
使用pstree -p 查看进程树
[email protected] $* 只在被双引号包起来的时候才会有差异
变量赋值:
变量名=值
赋值等号与值之间没有空格
[中括号里写变量的时候,记得加双引号]
(1) 可以是直接字串; 变量名=root
如果值为带空格或特殊字符时,请使用双引号和 \ 转义符号
(2) 变量引用: 变量名="$USER"
(3) 命令引用: 变量名=`指令`
变量名=$(指令)
变量引用:
${变量名}
$变量名
"双引号":弱引用,其中的变量引用会被替换为变量值
'单引号':强引用,其中的变量引用不会被替换为变量值,而保持原字符串
显示已定义的所有变量:
set
删除变量:
unset 变量名
只读变量:只能声明,但不能修改和删除
声明只读变量:
readonly 变量名
declare -r 变量名
查看只读变量:
readonly –p
位置变量:在脚本代码中调用通过命令行传递给脚本的参数
set -- 清空所有位置变量
进程使用退出状态来报告成功或失败
一般来讲,
0 代表成功,1-255代表失败
以下表为在未自定义退出状态码(exit)时的常见,可以参考
bash自定义退出状态码
exit [n]:自定义退出状态码
脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
退出状态可以使用变量作为值,退出状态码最大值为255,如果值超过255时,将会通过
取模运算 值/256 把状态码缩减到0~255整数值之间,比如:
exit 300
300/256 取模=44 400/256 取模=144
bash自带脚本测试
bash -n 语法检查
bash -x 脚本执行按步调试
算术运算
实现算术运算的方法:
(1) let 变量名=算术表达式
(2) var=$[算术表达式]
sum=$[uid10+uid20]
sum=$[$uid10+$uid20]
(3) var=$((算术表达式))
sum=$((uid10+uid20))
(4) declare –i 变量名 = 数值
(5) echo ‘算术表达式’ | bc
条件测试
若真,则返回0
若假,则返回1
1. test 语句
2. [空格 表达式 空格]
推荐使用第2种方法,因为我们去看系统本身自带的脚本编写使用的正是这一类方法。
第一个 [ 之后和第二个 ] 之前必须加上一个空格,否则会报错
上面的中括号是错误的格式,会报以下的错误
++++++++++++我是华丽的分界线++++++++++++++++++++
上面的中括号是错误的格式,会报以下的错误
++++++++++++我是华丽的分界线++++++++++++++++++++
以下才是正确的格式
可以判断4类条件
a.数值测试 b.字符串测试 c.文件测试 d.布尔逻辑组合测试条件
以下逐个看
a.数值测试
可以用在数字和变量(变量值是数字)上
注意,当碰到系统特殊符号的时候,记得 \ 转义
但是涉及到浮点值的时候,数值测试会有一个限制 ,我们来看一个例子:
变量$var1的值是浮点值,脚本对这个值进行了测试,显然这里就报错。因此,请记住
bash shell只能处理整数(zshell能很好的解决这个问题),当然,如果这个值只是用来
echo 输出是没问题的。
因此,此时shell的退出状态码也是为非0值了,也就是执行了else 之后的语句。
b.字符串测试
相等比较
在比较字符的相等性时,会将所有的标点和大小写情况都考虑在内的
使用调试工具来直观的看出状态码与结果
使用=或者== ,或者"" 和"空格" 的结果都是一致的
使用单引号也是一致的
这里需要注意的是,当值中带有空格的时候,变量没有双引号引起来会是报错的
当变量双引号引起来的时候,
正确输出
所以,在写 bash 脚本的时候,别偷懒,对于变量的引用最好都加上双引号!就变量引用上来说,虽然 zsh 在这点要强过 bash,但是处于兼容性的考虑,还是把双引号带上吧。
字符的比较
先来一个初学者常犯的错误
乍一看,没问题啊
可以当然我们使用ls查看当前目录的时候,发现$var2的值被重定向至以$var2的值,也就是abcdA的文件中了。这是一个不易觉察的严重问题。脚本把 > 解析成了重定向输出符号。同时,因为重定向成功,因此exit退出码为0,就会执行then语句了。
因此,使用 双引号 引起来 或 \ 转义解决吧。
这才是规范的脚本写法,别掉坑了哦~~
这才是正确的输出结果
字符串的大小写比较
在Shell的比较测试中,大写字母是被认为是小于小写字母的。这一点与sort命令恰好相反,同样的字符串用sort排序时,小写字母先出现,这是由于各个命令使用的排序技术不同造成的。
因此,总结为2句话:
shell编程时,小写字母 >(大于) 大写字母
sort排序时,小写字母 >(优先) 大写字母
如果出现以下大小写混合并相同的情况呢
那么就从左边开始比,第一位a相同,那就比第一位,b > A 根据以前的总结,结果就是
$var1 > $var2,不信就以图验证下
而sort命令则是以按小写字母>相同的大写字母排序的,注意哦~
如果是把数值的比较用了字符串的比较,那么你会怀疑你的数学是体育老师教的吧
数字越大就是大
最后的总结,如果使用错了操作符,可能无法得到正确的结果。
检查变量是否含有数据
-n 就是判断字符串是否为0
结果
++++++++++++我是华丽的分界线++++++++++++++++++++
结果
++++++++++++我是华丽的分界线++++++++++++++++++++
结果
++++++++++++我是华丽的分界线++++++++++++++++++++
结果,同时用双引号引起来的 空格 也是一样的结果
++++++++++++我是华丽的分界线++++++++++++++++++++
结果,没有定义就是0,就是没有值
++++++++++++我是华丽的分界线++++++++++++++++++++
-z 就是判断字符串是否为0
结果,与-n选项的结果是一致的
++++++++++++我是华丽的分界线++++++++++++++++++++
结果,用单引号引起来的 空格,结果也是一样的,与-n的结果是一致的
++++++++++++我是华丽的分界线++++++++++++++++++++
结果,用单引号引起来的的什么也没有,结果也是一样的,与-n的结果是一致的
++++++++++++我是华丽的分界线++++++++++++++++++++
结果,与-n 的结果是一致的
最后的总结,不管是单双引号引用的没有值变量,或者没有被声明的变量,值都是0.也就是空。
空和未初始化的变量会对shell脚本测试造成灾难性的影响,如果不是很确定一个变量的内容,最好在将其用于数值或字符串比较之前先通过- n 或 -z 来测试下变量是否含有值。
最后最后的警示演示:
清除下历史记录
#history -c
执行脚本,我的天啊,我的脚本原本的意图只是想删除/app/下面的全部文件而已,怎么变成了删除根目录下面的全部文件夹了呢!!太吓人了啊~~脚本有风险,且行且珍惜。哈哈~~
c.文件测试
用来测试Linux文件和目录的状态。
(选项后接file名,比如 -e file )
所谓的有效用户就是指,使用特殊的suid权限时,运行此程序的用户
因为这些操作符比较统一规范,自己多练习就好了,我就只给2个例子:
d.布尔逻辑组合测试条件
第一种方式:双中括号格式
如:[[ -r FILE ]] && [[ -w FILE ]]
[[ -r FILE ]] || [[ -w FILE ]]
第二种方式:必须使用测试命令test进行
如:test [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
test [ -f /bin/cat -o -x /bin/cat ] && cat /etc/fstab
高级特性
bash shell 提供了2项可在if-then语句中使用的高级特性:
a.用于数学表达式的双括号 (( ))
不需有将双括号中表达式里的运算符转义
建议括号内2边加空格
((空格 表达式 空格))
b.用于高级字符串处理功能的双中括号 [[ ]]
不是所有的shell都支持双中括号
建议双中括号内2边加空格
[[空格 表达式 空格]]
操作符号
va1++ (va1--)
自身先和后面的运算式运算,表达式的结果跟自身没有任何关系,再自身+-1的值赋与以后使用。
例子: a=5 b=2
a++ +b=7 (a+b=7,此时a的值为6)
上条表达式后的下一条表达式a的值已经变化了
a+b=8
++id ( --id)
例子: a=5 b=2
++a +b =8 (a+1=6,6+b=8,此时a的值为6)
上条表达式后的下一条表达式a的值已经变化了
a+b=8
自身先+-1,再和后面的运算式运算,表达式的结果跟自身没有任何关系,
以后的值就是原先自身先+-1
双括号范例
双中括号范例,扩展正则表达式
双中括号范例,扩展正则表达式
如果写成双等号的话,双中括号会自动转化为带转义的写法
注意红框的地方
第一章节到此结束,本人水平有限,如有错漏地方,欢迎指正。
以上是关于Shell 编程基础的主要内容,如果未能解决你的问题,请参考以下文章