知识内容:
1.shell编程预备知识
2.shell变量
3.表达式与运算符
4.分支循环语句
5.函数
一、shell编程预备知识
1.什么是shell编程
shell是与linux交互的基本工具,是一个命令解释器,它的作用是解释执行用户输入的命令及程序等,有两种执行命令的方式,如下所示:
- 交互式,用户每输入一条命令,shell就解释执行一条
- 批处理(batch),需要事先编写一个shell脚本,其中包含若干条命令,让shell一次将这些命令执行完
shell脚本及shell编程:当命令或程序语句不在命令行下执行,而是通过一个程序文件来执行时,该程序就被称为shell脚本,编写shell脚本的过程就称为shell编程
2.shell脚本的编写
(1)hello world
shell脚本一般可以使用vi编辑器或emacs编辑器编写,上述代码中第一行是声明脚本运行方式,在shell脚本中以#开头的为注释,不会被执行
(2)shell脚本的基本构成
运行结果如下:
以上代码的部分内容解释:
- 以#开头的为注释
- echo为输出语句,参数-n表示在显示信息时不自动换行
- whoami命令字符串左右的反引号(`)用于命令替换(转换),也就是将它所括起来的字符串视为命令执行,并将其输出的字符串在原地输出
(3)在shell脚本中包含外部脚本
. 脚本文件名
source 脚本文件名
实例:
注:上述代码中最后一行中的第二个.号表示当前目录
3.shell脚本的执行与调试
(1)执行
在命令行下直接执行:
chmod +x example
./example [参数]
在指定的shell下执行脚本:
shell名称 脚本名 [参数]
sh hello.sh
bash hello.sh
(2)调试
bash -v 脚本名
bash -x 脚本名
二、shell变量
1.变量类型
- 用户自定义变量(局部变量):由用户在shell程序中自定义
- 环境变量:系统环境中的一部分,不必去定义,可以在shell程序中使用,某些变量(如PATH)可以在shell中修改
- 内部变量:linux系统提供的一种特殊类型的变量,此类变量在程序中用来做出判断
注:常见的内部变量
$# 传送给shell程序的位置参数的数量
$? 最后命令的完成码或在shell程序内部执行的shell程序的返回值
$0 shell程序的名称
$* 调用shell程序时所传送的全部参数组成的单字符串
2.变量赋值和访问
(1)变量定义及赋值
- 变量定义:变量名=值
- 变量赋值:变量2=$变量1
注:定义变量时变量名不需加$,在赋值符号两边不允许有任何空格;变量名由字母、数字、下划线组成,可以由字母和下划线开头
把一个命令的结果作为变量的内容赋值的方法:
变量名=`ls` # 不推荐使用这种方法,因为容易和单引号混淆
变量名=$(ls) # 把命令用$()括起来,推荐使用这种方法
(2)变量访问:在变量名前加上一个$
$变量名表示输出变量,可以用$c和${c}两种语法
注意在一些场合中访问变量值时必须为变量名加上花括号{}
注:如果不给此时的skill加花括号,解释器会将skillScript当成一个变量,由于没有为这个变量赋值,其值为空。所以在字符串给所以变量加上花括号是一个好的编程习惯!
(3)只读变量和删除变量
- 使用readonly命令设置只读变量,只读变量的值不可改变
- 使用unset命令删除变量,变量被删除后不能再次使用,unset不能删除只读变量
(4)添加环境变量
使用export命令将变量添加到环境变量中,作为临时的环境变量(一种全局变量)
基本语法:export 变量名=变量值
注:export命令仅将变量加到环境中,如果要从程序的环境中删除该变量,则可以使用unset命令或env命令,env也可以临时地改变环境变量值
3.内部变量
变量 | 含义 |
---|---|
$0 | 脚本名 |
$1 -$9 | 位置参数1-9 |
${10} | 位置参数10 |
$# | 位置参数的个数 |
"$*" | 所有位置参数(作为单个字符串) |
"$@" | 所有位置参数(每个作为单独字符串) |
${#*} | 传递到脚本中的命令行参数的个数 |
${#*} | 传递到脚本中的命令行参数的个数 |
$? | 返回值 |
$$ | 脚本进程的PID |
$- | 传递到脚本中的标识 |
$_ | 之前命令的最后一个参数 |
$! | 运行在后台的最后一个作业的进程ID(PID) |
4.位置参数
- $0:获取当前执行的脚本文件名
- $n:获取当前执行的脚本的第n个参数,n=1...9,当n>10时就要用大括号括起来,例如:${10}
- $#:获取当前执行的脚本后面接的参数的总数
- $*:获取当前执行的脚本所有传参的参数
- $@:获取当前执行的脚本所有传参的参数
5.变量值的输出与读取
(1)echo命令(加上-n选项表示不换行输出)
str="OK!"
echo $str # 直接输出指定的字符串
echo "$str This is a test" # 将变量混在字符串中输出 mouth=4
echo "2018-${mouth}-3" # 将变量混在字符串中输出如果要将变量和其他字符连接在一起,就要使用花括号进行变量替换
(2)printf命令
printf格式:printf 格式字符串 [参数列表...] printf "hello! \n"
printf "%d %s\n" 100 "abc"
(3)read命令
read格式: read 变量
注:-p选项定义提示语句,-n选项对输入的字符进行计数,当输入的字符达到预定数目时自动退出,并将输入的数据复制给变量 read str
read -p "请输入两个数字" n1 n2
注:关于单引号、双引号、反引号的知识说明
单引号:关闭shell中所有的特殊符号使用和解释。说的简单点,就是单引号(‘ ’)中间的所有内容都作为普通的字符输出,就是说不管你是不是一些特殊的字符(如$,转移字符等)统统作为普通字符输出
双引号:关闭shell中的大部分的特殊字符,但保留部分,如$、转义字符\ (不包括\n \t等)、反引号(` `),而单引号(' ')则失效,作为普通字符输出
反引号:将反引号(` `)内的字符串当作shell命令来执行,返回值是命令的执行的结果,起到的是一个命令的替换作用
6.变量替换
变量替换根据变量的状态(是否为空是否定义)来改变它的值,使用花括号限定一个变量的开始和一个变量的结束
- ${var}:替换为变量本来的值
- ${var:-word}:如果变量var为空或已被删除,则返回word,但不改变var的值
- ${var:=word}:如果变量var为空或已被删除,则返回word,并将var的值设置为word
- ${var:?message}:如果变量var为空或已被删除,则将消息message发送到标准错误输出,可以用来检测变量var是否可以被正常赋值
- ${var:+word}:如果var被定义,则返回word,但不改变var的值
7.数组
数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小(与 PHP 类似),与大部分编程语言类似,数组元素的下标由0开始
Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:array_name=(value1 ... valuen)
数组实例:
三、表达式与运算符
1.表达式
expr命令:是一款表达式计算工具,使用它完成表达式的求值操作
let命令:计算整数表达式的值
expr命令使用:
expr 5 +3 n=1
m=5
expr $n + $m val=`expr 2 +2`
let命令使用:
n=1
m=5
let val=$n+$m
# 注意这种形式要求运算符和操作数之间不能有空格!
test命令:判断表达式的真假
test使用:test 逻辑表达式
test "abc"="xyz"
2.运算符
(1)算术运算: + - * / % = (2)整数关系运算符:
-eq 相等
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于 (3)字符串检测运算符:
= 检测两个字符串是否相等,相等返回true
!= 检测两个字符串是否相等,不等返回true
-z 检测字符串长度是否为0,为0返回true
-n 检测字符串长度是否为0,不为0返回true
str 检测字符串是否为空,不为空返回true (4)文件测试运算符 - 省略 (5)布尔运算符
-a 与 两个表达式均为true才返回true
-o 或 有一个表达式为true才返回true
! 非 表达式值为true返回false否则返回true
四、分支循环语句
1.if语句
(1)if结构
if [ 条件表达式 ]
then
语句序列
fi
注:条件表达式和[]之间必须有空格,否则会出现语法错误
if结构实例:
# !/bin/bash
a=1
b=2
if [ $a -lt $b ]
then
echo "a小于b"
fi
(2)if...else结构
if [ 条件表达式 ]
then
语句序列1
else
语句序列2
fi
if...else结构实例:
# !/bin/bash
a=1
b=2
if [ $a -lt $b ]
then
echo "a小于b"
else
echo "a不小于b"
fi
(3)if..elif...else结构
if [ 条件表达式1 ]
then
语句序列1
elif [ 条件表达式2 ]
then
语句序列2
elif [条件表达式3]
then
语句序列3
...
else
语句序列n
fi
if..elif...else结构实例:
# !/bin/bash
a=1
b=2
if [ $a == $b ]
then
echo "a等于b"
elif [ $a -gt $b ]
then
echo "a大于b"
elif [ $a -lt $b ]
then
echo "a小于b"
else
echo "所有条件均不满足"
fi
2.case语句
case 值 in
模式1)
语句序列1
;;
模式2)
语句序列2
;;
......
模式n)
语句序列n
;;
*)
其他语句序列
esac
实例:
# !/bin/bash
case $USER in
whxy)
echo "欢迎登录"
;;
root)
echo "超级管理员!"
echo "热烈欢迎"
;;
*)
echo "欢迎 $USER !"
;;
esac
3.循环语句
(1)while语句
while 测试条件
do
语句序列
done
实例:用while循环求1到100的和
# !/bin/bash
total=0
num=0
while [ $num -le 100 ]
do
total=`expr $total + $num`
num=`expr $num + 1`
done
echo "结果等于: $total"
(2)until语句
until 测试条件
do
语句序列
done
实例:用until循环求1到100的和
# !/bin/bash
total=0
num=0
until [ $num -gt 100 ]
do
total=`expr $total + $num`
num=`expr $num + 1`
done
echo "计算结果为: $total"
(3)for语句
for 变量 [ in 列表 ]
do
语句序列
done eg:
# 循环输出
for var in 1 2 3 4 5 6
do
echo $var
done # 显示主目录下的文件
for FILE in $HOME/*.*
do
echo $FILE
done
4.break和continue和exit
- break:退出循环
- continue:退出当前循环继续下次循环
- exit:退出一个shell程序
另外上述3种都可以指定值,例如break [3]就是退出3层循环,continue [2]表示跳出2层循环,exit [2]表示指定退出值为2
五、函数
1.函数的定义和调用
(1)函数的定义
[function] 函数名()
{
命令序列
[return 返回值]
}
function和return可以省略不写
(2)函数的调用
函数的调用:函数名 参数1 参数2 ...... 参数n
(3)实例
# !/bin/bash
Hello(){
echo "Hello world!"
}
Hello # 调用函数
2.函数的返回值
(1)return
shell函数的返回值,可以和其他语言的返回值一样,通过return语句返回。
示例:
#!/bin/bash
function test()
{
echo "arg1 = $1" # 输出第一个参数
if [ $1 = "" ]
then
return 1
else
return 0
fi
} echo "test 1:"
test 1
echo $? # print return result echo "test 0:"
test 0
echo $? # print return result echo "test 2:"
test 2
echo $? # print return result
(2)echo
其实在shell中,函数的返回值有一个非常安全的返回方式,即通过输出到标准输出返回。因为子进程会继承父进程的标准输出,因此,子进程的输出也就直接反应到父进程。
示例:
#!/bin/bash
function test()
{
echo "arg1 = $1"
if [ $1 = "" ]
then
echo ""
else
echo ""
fi
} echo "test 1"
test 1 echo "test 0"
test 0 echo "test 2"
test 2
注:不能向标准输出一些不是结果的东西(也就是不能随便echo一些不需要的信息),比如调试信息,这些信息可以重定向到一个文件中解决,特别要注意的是,脚本中用到其它类似grep这样的命令的时候,一定要记得1>/dev/null 2>&1来空这些输出信息输出到空设备,避免这些命令的输出
3.函数的参数
shell中调用函数时可以向其传递参数,与脚本一样,在函数体内部是通过$n的形式来获取参数的值
比如$1代表第一个参数,$2代表第二个参数
4.函数实战
(1)计算阶乘
设计一个shell程序计算n的阶乘。要求:
从命令行接收参数n;
在程序开始后立即判断n的合法性,即是否有参数,若有是否为正整数,若非法请给错误提示;
最后输出计算的结果
代码实现:
(2)
(3)