1、第一个shell程序
#!/bin/bash
echo "What is your name?"
read PERSON
echo "Hello, $PERSON"
备注:(1)“#!” 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell。echo命令用于向窗口输出文本;
(2)echo 是一个输出命令,可以用来输出数字、变量、字符串等;
(3)read read 命令从 stdin 获取输入并赋值给 PERSON 变量,最后在 stdout 上输出;
(4)运行Shell脚本有两种方式:作为可执行程序和作为解释器参数
作为可执行程序,这种方式#!/bin/bash必须要写,以便让系统查找到正确的解释器,执行之前通过chmod +x ./test.sh使脚本具有执行权限;
作为解释器参数,直接运行解释器,不需要在第一行指定解释器信息 /bin/sh test.sh。
补充:Shell注释,以“#”开头的行就是注释,会被解释器忽略。如果在开发的过程中遇到大段的代码需要注释起来,过一会又要取消注释,
可以将这一大段语句用一对花括号括起来,定义成一个函数。
2、Shell变量的定义、删除变量、只读变量、变量类型
变量是任何一种编程语言都必不可少的组成部分,变量用来存放各种数据。脚本语言在定义变量时通常不需要指明类型,直接赋值即可。
在Bash shell中,每一个变量的值都是字符串,无论给变量赋值的时候有没有使用引号,值都会以字符串的形式存在。
(1)变量定义,支持以下三种方式:
variable=value variable='value' variable="value"
注意:赋值号的周围不能有空格!!!
名命规则:a、变量名由数字、字母、下划线组成;
b、必须以字母或下划线开头;
c、不能使用shell里的关键字(通过help命令可以查看保留关键字)。
说明:variable是变量名,value是赋给变量的值。如果value不包含任何空白符(例如空格、Tab缩进等),那么可以不适用引号;
如果value包含了空白符,就必须使用引号包围起来,以单引号‘’包围变量的值时,单引号里面是什么就会输出什么,即使内容里面有变量或者命令也会把它们
原样输出,这种方式比较适合定义显示纯字符串的情况(不希望解析变量和命令),以双引号“”包围变量的值时,输出时会先解析里面的变量和命令,这种方式
比较适合字符串中附带有变量和命令并且想将其解析后再输出的变量定义。
只读变量:使用readonly命令可以将变量定义为只读变量,其值不能被改变,eg: name="lilei" readonly name
(2)使用变量,使用一个定义过的变量,只要在变量名前面加美元符号$即可,如:
name="lilei"
echo $name
echo ${name}
说明:变量名外面的花括号{ }是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,建议给所有变量加上{}。
(3)将命令的结果赋值给变量,常用的方法有以下两种;
variable=`command` variable=$(command)
第一种使用反引号包围命令(不建议),第二种方式用$()包围起来,区分明显。
eg: log=$(cat log.txt)
echo $log
(4)删除变量,使用unset可以删除变量。语法:
unset variable //变量被删除后不能再次使用,unset命令不能删除只读变量。
(5)变量类型,运行shell时,会同时存在三种变量:
a、局部变量 :局部变量在脚本或命令中定义,仅在当前shell实例中有效,其它shell启动的程序不能访问局部变量。
b、环境变量 :所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
c、shell变量 :shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行。
3、Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
$0 当前脚本的文件名;
$n 传递给脚本或函数的参数,n代表是一个数字,表示第几个参数;
$# 传递给脚本或函数的参数个数;
$* 传递给脚本或函数的所有参数;
$@ 传递给脚本或函数的所有参数,被双引号(" ")包含时,与 $* 稍有不同;
$? 上个命令的退出状态,或函数的返回值;
$$ 当前Shell进程ID,对于Shell脚本来说就是这些脚本所在的进程ID。
$* 和 $@ 的区别:都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。但是当它们被双引号(" ")包含时,
1"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。
4、Shell替换:shell变量替换,命令替换,转义字符
(1)命令替换,指Shell可以先执行命令,将输出结果暂时保存,在适当的地方输出。语法:`command`
#!/bin/bash
DATE=`date`
echo "Date is $DATE"
USERS=`who | wc -l`
echo "Logged in user are $USERS"
UP=`date ; uptime`
echo "Uptime is $UP"
输出结果:Date is Thu Jul 2 03:59:57 MST 2009
Logged in user are 1
Uptime is Thu Jul 2 03:59:57 MST 2009
03:59:57 up 20 days, 14:03, 1 user, load avg: 0.13, 0.07, 0.15
(2)变量替换,变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值。
变量替换形式:
$(var) 变量本来的值
$(var;-word) 如果变量var为空或已被删除(unset),那么返回word,但不改变var的值。
$(var;=word) 如果变量var为空或已被删除(unset),那么返回word,并将var的值设置为word。
$(var:?message) 如果变量var为空或已被删除(unset),那么将消息message送到标准错误输出,可以用来检测
变量var是否可以被正常赋值。若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。
(3)转义字符,如果表达式中包含特殊字符,Shell将会进行替换,例如,在双引号中使用变量就是一种替换,转义字符也是一种替换。
eg: #!/bin/bash
a=10
echo -e "Value of a is $a
"
输出结果:Value of a is 10
补充:-e表示对转义字符进行替换,如果不使用-e选项,将会原样输出:Value of a is 10
以下转义字符都可以在echo中使用:
\ 反斜杠 a 警报,响铃 退格(删除键)
f 换页(FF),将当前位置移到下页开头
换行
回车 水平制表符(tab键) v 垂直制表符
5、Shell运算符:Shell算术运算符、关系运算符、布尔运算符、字符串运算符等
Bash支持很多运算符,但是原生bash不支持简单的数学运算,但是可以通过其他命令实现,例如awk、expr等。
(1)算术运算符,expr是一款表达式计算工具,使用它能完成表达式的求值工作,例如:
两个数相加
#!/bin/bash
val=`expr 2 + 2`
echo "Total value : $val"
注意:表达式和运算符之间要有空格,例如2+2是不对的,必须写成2 + 2;
完整的表达式要被``包含,这个符号不是常用的单引号,在Esc下面的符号。
算术运算符列表(a=10,b=20):
运算符 说明 举例
+ 加法 `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
注意:条件表达式要放在方括号之间,并且要有空格,例如[$a==$b]是错误的,必须写成[ $a == $b ]
(2)关系运算符,关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 true。
-ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
-ge 检测左边的数是否大等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。
(3)布尔运算符
运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
(4)字符串运算符 a="abc" b="efg"
运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
-n 检测字符串长度是否为0,不为0返回 true。 [ -z $a ] 返回 true。
str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。
(5)文件测试运算符,用于检测Unix文件的各种属性。
例如,变量 file 表示文件“/var/www/tutorialspoint/unix/test.sh”,它的大小为100字节,具有 rwx 权限。下面的代码,将检测该文件的各种属性:
操作符 说明 举例
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
-c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -b $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。
6、Shell字符串
字符串是shell编程中最常见最有用的数据类型,字符串可以用单引号,也可以用双引号,也可以不用引号。
a) 单引号: str='this is a string'
注意:单引号里面的所有字符都会原样输出,单引号字符串中的变量是无效的;
单引号字符串中不能出现单引号。
b) 双引号:your_name='qinjx'
str="Hello, I know your are "$your_name"!
"
注意:双引号里可以有变量,也可以出现转义字符。
c)拼接字符串
your_name="qinjx"
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
d)获取字符串长度
string=“abcd”
echo ${#string} #输出4
e)提取子字符串
string="alibaba is a great company"
echo ${string:1:4} #输出liba
f)查找字符串
string="alibaba is a great company"
echo `expr index "$string" is`
7、Shell数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小,类似与C语言,数组元素的下标由0开始编号。获取
数组中的元素要利用下标,下标可以是整数或者算术表达式,其值应该大于或等于0。
(1)定义数组,在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。
eg: array_name=(value0 value1 value2)
可以单独定义数组的各个分量,可以不使用连续的下标,并且下标的范围没有限制:
array_name[0]=value0
array_name[1]=value1
array_name[3]=value3
(2)读取数组,其一般格式是:
${array_name[index]}
可以使用@或*获取数组的所有元素,例如:
${array_name[*]} 或 ${array_name[@]}
(3)获取数组的长度,获取数组长度与获取字符串长度的方法相同,例如:
length=${#array_name[@]} 或 length=${#array_name[*]}
8、Shell echo命令
echo是一个Shell的一个内部指令,用于在屏幕上打印出指定的字符串。命令格式: echo arg
还可以使用echo实现更复杂的输出格式控制:
(1) echo ""It is a test"" 结果将是:"It is a test" 双引号也可以省略。
(2) 如果变量与其他字符相连,需要使用大括号({})
mount=8 echo "${mount}-l-2019" 结果将是:4-1-2019
(3) 显示换行 echo "OK!
" echo "It is a test"
输出: OK!
It is a test
(4) 显示不换行 echo "OK!c" echo "It is a test"
输出:OK!It is a test
(5) 显示结果重定向至文件
echo "It is a test" > myfile
(6) 原样输出字符串(不进行转义),请使用单引号。
eg: echo '$name"'
(7) 显示命令执行结果
eg: echo `date` 结果将显示当前日期
注意:从以上可以看出,双引号可有可无,单引号主要是用在原样输出中。
9、Shell test命令
Shell中的test命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
(1)数值测试
-eq 等于则为真 -ne 不等于则为真 -gt 大于则为真
-ge 大于等于则为真 -lt 小于则为真 -le 小于等于则为真
num1=100,num2=100
if test $[num1] -eq $[num2]
then
echo 'The two numbers are equal!'
else
echo 'The two numbers are not equal!'
fi
输出:The two numbers are equal!
(2)字符串测试
= 等于则为真 != 不等于则为真
-z字符串 字符串长度伪则为真 -n字符串 字符串长度不伪则为真
num1=100,num2=100
if test num1=num2
then
echo 'The two strings are equal!'
else
echo 'The two strings are not equal!'
fi
输出:The two strings are equal!
(3)文件测试
-e 文件名 如果文件存在则为真 -r 文件名 如果文件存在且可读则为真
-w 文件名 如果文件存在且可写则为真 -x 文件名 如果文件存在且可执行则为真
-s 文件名 如果文件存在且至少有一个字符则为真 -d 文件名 如果文件存在且为目录则为真
-f 文件名 如果文件存在且为普通文件则为真 -c 文件名 如果文件存在且为字符型特殊文件则为真
-b 文件名 如果文件存在且为块特殊文件则为真
cd /bin
if test -e ./bash
then
echo 'The file already exists!'
else
echo 'The file does not exists!'
fi
输出:The file already exists!
补充:Shell还提供了与( ! )、或( -o )、非( -a )三个逻辑操作符用于将测试条件连接起来,其优先级为:“!”最高,“-a”次之,“-o”最低。例如:
cd /bin
if test -e ./notFile -o ./bash
then
echo 'One file exists at least!'
else
echo 'Both dose not exists!'
fi
输出:One file exists at least!
10、Shell if else命令
if语句通过关系运算符判断表达式的真假来决定执行哪个分支。Shell有三种if...else语句:
(1)if...fi语句
语法: if [ expression ]
then
Statement(s) to be executed if expression is true
fi
说明:如果expression返回true,then后面的语句将会被执行;如果返回false,不会执行任何语句。
最后必须以fi来闭合if,expression和方括号([])之间必须有空格,否则将会有语法上的错误。
(2)if...else...fi语句
语法 if [ expression ]
then
Statement(s) to be executed if expression is true
else
Statement(s) to be executed if expression is not true
fi
说明:如果 expression 返回 true,那么 then 后边的语句将会被执行;否则,执行 else 后边的语句。
(3)if...elif...else...fi语句
语法: if [ expression 1 ]
then
Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
Statement(s) to be executed if expression 3 is true
else
Statement(s) to be executed if no expression is true
fi
说明:哪一个 expression 的值为 true,就执行哪个 expression 后面的语句;如果都为 false,那么不执行任何语句。
11、Shell for循环
for 变量 in 列表
do
command1
command2
command3
done
列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。
in列表是可选的,如果不用它,for循环使用命令行的位置参数。
显示主目录下以.bash开头的文件:
for FILE in $HOME/.bash*
do
echo $FILE
done
运行结果:
/root/.bash_history
/root/.bash_logout
/root/.bash_profile
/root/.bashrc
13、Shell until循环
until循环执行一系列命令直至条件为true时停止。until循环与while循环在处理方式上正好相反。一般while循环优先于
until循环:
until command
do
Statement(s) to be executed until command is true
done
command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
14、Shell函数、函数参数、输入输出重定向、shell文件包含
http://c.biancheng.net/cpp/view/7011.html
shell 正则表达式