title: Shell 编程
tags:shell
- Shell
categories:编程
- Linux
[TOC]数组
注意: 不要将脚本命名为test
,由于test
是一个内置的应用程序bash
#!/bin/bash # File: hello.sh echo "Hello World !"
bovenson@ThinkCentre:~/Git/neu-ip-gateway-manager$ bash hello.sh Hello World!
定义ssh
v="This is a variable."
注意编程语言
使用函数
使用一个定义过的变量,只要在变量名前面加美圆符号便可工具
#!/bin/bash # File: hello.sh v="This is a variable." echo $v echo ${v} # 变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界
bovenson@ThinkCentre:~/Tmp$ bash hello.sh This is a variable. This is a variable. bovenson@ThinkCentre:~/Tmp$
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界, 推荐给全部变量加上花括号,这是个好的编程习惯, 好比下面这种状况:oop
for skill in Ada Coffe Action Java; do echo "I am good at ${skill}Script" done
只读变量测试
使用 readonly 命令能够将变量定义为只读变量,只读变量的值不能被改变。
#!/bin/bash # File: hello.sh my_name="szk" readonly my_name my_name="bovenson"
bovenson@ThinkCentre:~/Tmp$ bash hello.sh hello.sh:行6: my_name: 只读变量 bovenson@ThinkCentre:~/Tmp$
删除变量
unset variable_name
注意:
变量类型
字符串是shell编程中最经常使用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串能够用单引号,也能够用双引号,也能够不用引号。单双引号的区别跟PHP相似。
str='this is a string'
单引号字符串的限制:
my_name='szk' str="Hello, I know your are \"$my_name\"! \n"
双引号的优势:
#!/bin/bash # File: hello.sh my_name="szk" greeting="hello, "$my_name" !" greeting_1="hello, ${my_name} !" echo $greeting $greeting_1
bovenson@ThinkCentre:~/Tmp$ bash hello.sh hello, szk ! hello, szk ! bovenson@ThinkCentre:~/Tmp$
#!/bin/bash # File: hello.sh my_name="szk" echo ${#my_name}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh 3
#!/bin/bash # File: hello.sh slogon="One World, One Dream!" echo ${slogon:4:5} # 这里4是开始下标, 5是截取长度
bovenson@ThinkCentre:~/Tmp$ bash hello.sh World
#!/bin/bash # File: hello.sh slogon="One World, One Dream!" index=`expr index "$slogon" W` # 查找W字符 echo ${index} index=`expr index "$slogon" Dra` # 查找字符D, r, a中的一个 echo ${index}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh 5 7
假设有变量 var=http://www.aaa.com/123.htm
方法一
# # 号截取,删除左边字符,保留右边字符 echo ${var#*//} # 其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的全部字符 # 即删除 http:// # 结果是 :www.aaa.com/123.htm
方法二
# ## 号截取,删除左边字符,保留右边字符。 echo ${var##*/} # ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的全部字符 # 即删除 http://www.aaa.com/ # 结果是 123.htm
方法三
# %号截取,删除右边字符,保留左边字符 echo ${var%/*} # %/* 表示从右边开始,删除第一个 / 号及右边的字符 # 结果是:http://www.aaa.com
方法四
# %% 号截取,删除右边字符,保留左边字符 echo ${var%%/*} # %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符 # 结果是:http:
方法五
# 从左边第几个字符开始,及字符的个数 echo ${var:0:5} # 其中的 0 表示左边第一个字符开始,5 表示字符的总个数。 # 结果是:http:
方法六
# 从左边第几个字符开始,一直到结束 echo ${var:7} # 其中的 7 表示左边第8个字符开始,一直到结束 # 结果是 :www.aaa.com/123.htm
方法七
# 从右边第几个字符开始,及字符的个数 echo ${var:0-7:3} # 其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。 # 结果是:123
方法八
# 从右边第几个字符开始,一直到结束 echo ${var:0-7} # 表示从右边第七个字符开始,一直到结束。 # 结果是:123.htm
注:
定义数组
在Shell中,用括号来表示数组,数组元素用"空格"符号分割开:
数组名=(值1 值2 ... 值n)
例如:array_name=(value0 value1 value2 value3)
或者:
array_name=( value0 value1 value2 value3 )
还能够单独定义数组的各个份量:
array_name[0]=value0 array_name[1]=value1 . . . array_name[n]=valuen
读取数组
读取数组元素值的通常格式是:
${数组名[下标]}
例如:
valuen=${array_name[n]}
使用@符号能够获取数组中的全部元素,例如:
echo ${array_name[@]}
#!/bin/bash # File: hello.sh slogon=("One" "World" "," "One" "Dream!") echo ${slogon[0]} echo ${slogon[1]} echo ${slogon[@]}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh One World One World , One Dream! bovenson@ThinkCentre:~/Tmp$
获取数组长度
#!/bin/bash # File: hello.sh slogon=("One" "World" "," "One" "Dream!") # 获取数组长度的方法与获取字符串长度的方法相同 echo ${#slogon[@]} echo ${#slogon[*]}
bovenson@ThinkCentre:~/Tmp$ bash hello.sh 5 5
示例:
#-------------------------------------------- # 这是一个注释 # author:菜鸟教程 # site:www.runoob.com # slogan:学的不只是技术,更是梦想! #-------------------------------------------- ##### 用户配置区 开始 ##### # # # 这里能够添加脚本描述信息 # # ##### 用户配置区 结束 #####
每一行加个#符号太费力了,能够把这一段要注释的代码用一对花括号括起来,定义成一个函数,没有地方调用这个函数,这块代码就不会执行,达到了和注释同样的效果.
位置参数
咱们能够在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 表明一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
位置参数包括命令名和命令行参数.在shell脚本中, 按照它们在命令行上的位置来引用它们(如命令command a b c
中参数a
,b
,c
的位置 ). 不能经过赋值语句改变位置参数的值.
bash的内置命令set
能够修改除调用程序名(命令名)之外的任意位置参数, 可是在tcsh中, set
内置命令不能改变位置参数的值
在脚本中使用 $0 $1 来获取位置参数
#!/bin/bash # File: hello.sh echo "Shell 传递参数实例!"; echo "执行的文件名:$0"; echo "第一个参数为:$1"; echo "第二个参数为:$2"; echo "第三个参数为:$3";
bovenson@ThinkCentre:~/Tmp$ bash hello.sh v1 v2 v3 v4 v5 v6 v7 Shell 传递参数实例! 执行的文件名:hello.sh 第一个参数为:v1 第二个参数为:v2 第三个参数为:v3 bovenson@ThinkCentre:~/Tmp$
几个特殊字符用来处理参数
字符 | 说明 |
---|---|
$# |
传递到脚本的参数个数 |
$* |
以一个单字符串显示全部向脚本传递的参数。如$* 用" 括起来的状况、以$1 $2 … $n 的形式输出全部参数。 |
$$ |
脚本运行的当前进程ID号 |
$! |
后台运行的最后一个进程的ID号 |
$@ |
与$* 相同,可是使用时加引号,并在引号中返回每一个参数。如$@ 用" 括起来的状况、以$1 $2 … $n 的形式输出全部参数。 |
$- |
显示Shell使用的当前选项,与set命令功能相同。 |
$? |
显示最后命令的退出状态。0表示没有错误,其余任何值代表有错误。 |
#!/bin/bash # File: hello.sh echo "Shell 传递参数实例!"; echo "第一个参数为:$1"; echo "参数个数为:$#"; echo "传递的参数做为一个字符串显示:$*";
bovenson@ThinkCentre:~/Tmp$ bash hello.sh v1 v2 v3 v4 v5 v6 v7 Shell 传递参数实例! 第一个参数为:v1 参数个数为:7 传递的参数做为一个字符串显示:v1 v2 v3 v4 v5 v6 v7
$*
与 $@
区别
原生bash不支持简单的数学运算,可是能够经过其余命令来实现,例如 awk 和 expr,expr 最经常使用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操做。例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):
#!/bin/bash val=`expr 2 + 2` echo "两数之和为 : $val"
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | `expr $a + $b` 结果为 30 |
- | 减法 | `expr $a - $b` 结果为 -10 |
* | 乘法 | `expr $a \* $b` 结果为 200 |
/ | 除法 | `expr $b / \$a` 结果为 2 |
% | 取余 | `expr $b % $a` 结果为 0 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a |
== | 相等。用于比较两个数字,相同则返回 true | [ $a == $b ] 返回 false |
!= | 不相等。用于比较两个数字,不相同则返回 true | [ $a != \$b ] 返回 true |
注意:
运算符 | 说明 |
---|---|
-eq | 检测两个数是否相等,相等返回 true |
-ne | 检测两个数是否相等,不相等返回 true |
-gt | 检测左边的数是否大于右边的,若是是,则返回 true |
-lt | 检测左边的数是否小于右边的,若是是,则返回 true |
-ge | 检测左边的数是否大于等于右边的,若是是,则返回 true |
-le | 检测左边的数是否小于等于右边的,若是是,则返回 true |
运算符 | 说明 |
---|---|
! | 非运算,表达式为 true 则返回 false,不然返回 true |
-o | 或运算,有一个表达式为 true 则返回 true |
-a | 与运算,两个表达式都为 true 才返回 true |
运算符 | 说明 | ||
---|---|---|---|
&& | 逻辑的 AND | ||
\ | \ | 逻辑的 OR |
运算符 | 说明 |
---|---|
= | 检测两个字符串是否相等,相等返回 true |
!= | 检测两个字符串是否相等,不相等返回 true |
-z | 检测字符串长度是否为0,为0返回 true |
-n | 检测字符串长度是否为0,不为0返回 true |
str | 检测字符串是否为空,不为空返回 true, 如 [ $a ] |
文件测试运算符用于检测 Unix 文件的各类属性
操做符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是不是块设备文件,若是是,则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是不是字符设备文件,若是是,则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是不是目录,若是是,则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是不是普通文件(既不是目录,也不是设备文件),若是是,则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位,若是是,则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit),若是是,则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是不是有名管道,若是是,则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位,若是是,则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读,若是是,则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写,若是是,则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行,若是是,则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在,若是是,则返回 true。 | [ -e $file ] 返回 true。 |
if test-command then comands fi
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
if condition then command1 command2 ... commandN else command fi
if condition1 then command1 elif condition2 then command2 else commandN fi
for var in item1 item2 ... itemN do command1 command2 ... commandN done
for var in item1 item2 ... itemN; do command1; command2… done;
# 示例 1 for loop in 1 2 3 4 5 do echo "The value is: $loop" done # 输出 The value is: 1 The value is: 2 The value is: 3 The value is: 4 The value is: 5 # 示例 2 for str in 'This is a string' do echo $str done # 输出 This is a string
while condition do command done
# 示例 1 #!/bin/sh int=1 while(( $int<=5 )) do echo $int let "int++" done # 输出 1 2 3 4 5 # 示例 2 echo '按下 <CTRL-D> 退出' echo -n '输入你最喜欢的电影名: ' while read FILM do echo "是的!$FILM 是一部好电影" done
while : do command done # 或者 while true do command done # 或者 for (( ; ; ))
until condition do command done # 条件可为任意测试条件,测试发生在循环末尾,所以循环至少执行一次—请注意这一点
case 值 in 模式1) command1 command2 ... commandN ;; 模式2) command1 command2 ... commandN ;; esac # case的语法和C family语言差异很大,它须要一个esac(就是case反过来)做为结束标记 # 每一个case分支用右圆括号,用两个分号表示break。
在循环过程当中,有时候须要在未达到循环结束条件时强制跳出循环,Shell使用两个命令来实现该功能:break和continue。
shell中函数的定义格式以下:
[ function ] funname [()] { action; [return int;] }
# 示例 1 demoFun(){ echo "这是个人第一个 shell 函数!" } echo "-----函数开始执行-----" demoFun echo "-----函数执行完毕-----" # 示例 2 funWithReturn(){ echo "这个函数会对输入的两个数字进行相加运算..." echo "输入第一个数字: " read aNum echo "输入第二个数字: " read anotherNum echo "两个数字分别为 $aNum 和 $anotherNum !" return $(($aNum+$anotherNum)) } funWithReturn echo "输入的两个数字之和为 $? !"
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容做为输入。 |
须要注意的是文件描述符 0 一般是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。