shell编程
shell简介
- shell是一个命令行解释器,它读取用户输入,然后执行命令。
- shell的用户输入通常来自于终端(交互式shell)或来自于文件(shell脚本)。
- UNIX系统上有很多种Shell,Linux下bash最为常用。
- shell脚本是一种脚本语言,我们只需使用任意文本编辑器,按照语法编写相应程序,增加可执行权限,即可在安装shell命令解释器的环境下执行。
脚本的调用形式
1.打开终端时系统自动调用:/etc/profile 或 ~/.bashrc
- /etc/profile :此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行,系统的公共环境变量在这里设置。开始自启动的程序,一般也在这里设置
- ~/.bashrc:在用户自己的家目录中的.bashrc 登录时会自动调用,打开任意终端时也会自动调用这个文件一般设置与个人用户有关的环境变量,如交叉编译器的路径等等。
2.用户手动调用:用户编写的shell脚本
运行一个shell脚本
- #! 用来声明脚本由什么shell解释,否则使用默认shell
- # 号代表注释当前行
- shell脚本文件通常以 .sh 为结尾,没有也可以运行
- 用命令chmod +x hello.sh给脚本hello.sh增加可执行权限后 ./hello.sh直接运行
- 若在终端使用bash hello.sh则指明了用bash,#!不起作用
- 若在终端使用 . hello.sh 则不启动新shell,使用当前shell执行
hello.sh
#!/bin/bash
# 编写hello world脚本
echo "Hello World!"
执行成功后终端显示: Hello World!
变量
1.自定义变量
-
shell中变量类型只有整型和字符型
-
定义变量:变量名=变量值(等号两边不能有空格)
-
引用变量:$变量名
-
显示变量:echo $变量名(用 \ 转义字符时echo加 -e 选项)
-
清除变量:unset 变量名
-
read [选项] [变量名]:从标准输入读取输入存取到一个标准变量中
-
readonly 变量名=变量值:变量定义时使用后该变量不能被改变或清除
#!/bin/bash num=666 str="NB" echo $str$num read -p "输两个变量呗" data1 data2 #选项-p可输入提示信息 echo "您输入的是:$data1和$data2" #""内的变量会被解释,''内的全部视为字符 unset num data1 echo $str $num $data1 $data2
终端运行:
2.环境变量
环境变量概念
- 用户自定义变量只在当前的shell中生效。而环境变量会在当前shell和这个shell的所有子shell当中有效。如果把环境变量写入相应的配置文件,那么这个环境变量就会在所有的shell中生效
- 一部分变量由系统来定义的,系统环境变量,这个变量名称是不变的,不能更改,一旦改了就失去作用了。只能修改它的值,作用固定的。有一部分是可以用户添加的,环境变量可以手工添加自己定义的环境变量。
操作环境变量
-
查看环境变量:env
-
声明环境变量:export 变量名=变量值(临时有效)
-
删除环境变量:unset变量名
-
导出环境变量: source 脚本文件
-
若要永久生效环境变量需要修改下面的系统文件(修改后使用source该文件生效):
- ~/.bashrc文件在每次启动sell时被读取
- /etc/profie文件在系统启动时被读取
常用的系统环境变量
- HOME: 使用者的目录地址
- BASH: 目前使用的shell
- HISTSIZE: 保留历史命令的数目上限
- PATH:系统默认的可执行文件搜索路径
- LANG:系统使用的编码。很多程序是根据系统指定的编码去解析输入文件,如果编码不正确,很多文件就无法正确解。
- RANDOM:随机产生一个0~32767之间的随机数
- PS1:即命令提示符的格式,就是shell命令行前方的图标
- $:表示当前shell的pid
3.预设变量(参数变量)
-
当我们在终端运行脚本时,输入的参数信息会被定义好的预设变量捕捉,我们可以直接使用
-
$#:统计脚本运行时携带的命令行参数的个数
-
$0:获取shell在命令行启动的脚本名
-
$1:获取第1个参数
-
$2:获取第2个参数
… -
$9:获取第9个参数
-
${10}:获取第10个参数(大于9的参数用{}括起来)
-
$* :所有参数列表, 以"$1" “ 2 " … " 2" … " 2"…"n” 的形式输出所有参数
-
$@:所有参数列表, 以"$1 $2 … $n"的形式输出所有参数
-
$?:上一个运行命令的返回值(命令成功为0,失败返回>0)
-
$$ :当前shell进程的pid
4.其它
-
在双引号中的系统命令要放在反引号` `内(在你键盘1左边)
echo "当前路径为:`pwd`"
-
(命令序列):()内的命令有子shell完成,不影响当前shell的变量
-
{命令序列}:{}内的命令在当前shell内完成
变量的算术运算
运算符
运算符 | 含义 |
---|---|
+,- | 加法,减法 |
*,/,% | 乘,除,取余 |
** | 幂运算 |
++,– | 自增加,自减少 |
<, <=, >, >= | 比较符号 |
=, +=, -=, *=, /=, %= | 赋值运算 |
shell中常用的运算命令
操作 | 含义 |
---|---|
(( )) | 用于整数运算 |
let | 用于整数运算,与(())类似 |
expr | 用于整数运算,功能相对较多 |
bc | linux下的计算器,适合小数及整数运算 |
$[ ] | 用于整数运算 |
条件测试语句
-
test命令:用于测试字符串、文件状态和数字
-
test命令有两种格式:test condition 或 [ condition ]
-
使用方括号时,要注意在条件两边加上空格
-
当test测试条件成立时返回0;条件不成立返回1
-
可用 $? 搜集返回信息
1.文件测试
参数 | 说明 |
---|---|
-e 文件名 | 文件是否存在 |
-s 文件名 | 文件是否为空 |
-r 文件名 | 文件是否为可读文件 |
-w 文件名 | 文件是否为可写文件 |
-r 文件名 | 文件是否为可执行文件 |
-b 文件名 | 文件是否为块设备文件 |
-c 文件名 | 文件是否为字符文件 |
-d 文件名 | 文件是否为目录文件 |
-f 文件名 | 文件是否为普通文件 |
- L 文件名 | 文件是否为软连接 |
-S 文件名 | 文件是否为套接字文件 |
-p 文件名 | 文件是否为管道文件 |
示例代码:
#!/bin/bash
read -p "请输入文件名>" filename
echo "是为0,否为1"
test -e $filename
echo "是否存在?$?"
test -s $filename
echo "是否为空?$?"
test -r $filename
echo "是否可读?$?"
test -w $filename
echo "是否可写?$?"
test -x $filename
echo "是否可执行?$?"
2.字符串测试
参数 | 说明 |
---|---|
s1 = s2 | 字符串s1与s2是否相同 |
s1 != s2 | 字符串s1与s2是否不同 |
-z s1 | 字符串s1长度是否为0 |
-n s1 | 字符串s1长度是否不为0 |
3.数值测试
参数 | 说明 |
---|---|
a -eq b | a是否等于b |
a -ne b | a是否不等于b |
a -gt b | a是否大于b |
a -ge b | a是否大于等于b |
a -lt b | a是否小于b |
a -le b | a是否小于等于b |
4.逻辑测试
逻辑与:[条件1]&&[条件2] 或者test 条件1 -a 条件2
逻辑或:[条件1] || [条件2] 或者test 条件1 -o 条件2
逻辑非:[! 条件] 或者 test ! 条件
控制语句
if语句
格式:
if [ 条件1 ] ; then
命令序列1
elif [ 条件2 ] ; then
命令序列2
else
命令序列3
fi
或者
if [ 条件1 ]
then
命令序列1
elif [ 条件2 ]
then
命令序列2
else
命令序列3
fi
代码示例:
#!/bin/bash
read -p "请选择yes或no >>" data
if [ "$data" = "yes" ] ;then
echo "你选择了yes"
elif [ "$data" = "no" ] ;then
echo "你选择了no"
else
echo "你选的啥(⊙_⊙)?"
fi
case语句
格式:
case $变量名 in
"变量1")
命令序列1
;;
"变量2")
命令序列2
;;
...
*)
其它命令序列
;;
esac
代码示例:
#!/bin/bash
read -p "请选择LS或PWD >>" cmd
case $cmd in
PWD)
pwd
;;
LS)
ls
;;
N*|n*) #只要是以N或n开头的字符串就会执行,*代表任意若干个字符,?代表任意一个字符
echo "NB 666 My Baby!"
;;
*)
echo "小老弟你又输的啥(⊙_⊙)?"
;;
esac
for语句
- declare为bash内建命令可以用来声明shell变量和设置变量属性,-i选项可以强制把变量转成int型变量参与运算
形式1:
for((初始值;限制值;执行步阶))
do
命令序列
done
#!/bin/bash
declare -i i=0
for((i=1;i<9;i++))
do
echo "这是我第$i次循环"
done
形式2:
for 变量名 in 值1 值2 值3 ...
do
命令序列
done
for card in 3 4 5 6 7 8 9 10 J Q K A 2 blackJoker redJoker
do
echo "我出一张$card!"
done
while语句
- 满足条件则开始循环
形式:
while [条件]
do
命令序列
done
#!/bin/bash
declare -i i=9
while [ $i -gt 0 ]
do
echo "我在$i楼"
let i-=1
done
echo "我到楼下了"
until语句
- 满足条件则退出循环
形式:
until [条件]
do
命令序列
done
#!/bin/bash
str=2333
until [ $str = "quit" ]
do
read -p "输入quit退出,不然我再问你一遍(`・ω・´)> " str
done
关键字break和continue
- break:跳出整个循环
- continue:跳过当前步骤
shell函数
-
格式:
function 函数名(){ 命令... }
- function可以缺省不写, function不缺省时()可不写
-
调用:函数名 参数1 参数2 参数3…
-
向函数内传递参数时同脚本的参数变量,$1 $2 $3…
-
函数内return返回的值用 #? 搜集
-
调用其他脚本文件的函数要用source 文件名导出其脚本文件
输入三个数并进行升序排序
#!/bin/bash
rank(){
num1=$1
num2=$2
num3=$3
tmp=0
# 如果 num1 大于 num2,就把 num1 和和 num2 的值对调,确保 num1 变量中存的是最小值
if [ $num1 -gt $num2 ];then
tmp=$num1
num1=$num2
num2=$tmp
fi
# 如果 num1 大于 num3,就把 num1 和 num3 对调,确保 num1 变量中存的是最小值
if [ $num1 -gt $num3 ];then
tmp=$num1
num1=$num3
num3=$tmp
fi
# 如果 num2 大于 num3,就把 num2 和 num3 对标,确保 num2 变量中存的是小一点的值
if [ $num2 -gt $num3 ];then
tmp=$num2
num2=$num3
num3=$tmp
fi
echo "排序后数据(从小到大)为:$num1,$num2,$num3"
}
num1=0
until [ $num1 = 886 ] #最小值为886退出程序
do
# 依次提示用户输入 3 个整数,脚本根据数字大小依次排序输出 3 个数字
read -p "请输入一个整数:" num1
read -p "请输入一个整数:" num2
read -p "请输入一个整数:" num3
rank $num1 $num2 $num3
done