吾不知青天高,黄地厚,
唯见月寒日暖,来煎人寿。
------ 李贺《苦昼短》
一.shell编程基础
(一)基本概念
shell脚本:
一个包含若干行shell或者Linux命令的Shell程序。
Shell:
shell有很多含义,一个程序,一个脚本,一个环境
shell 种类:
/bin/bash /bin/sh /bin/csh /bin/tcsh /bin/ksh等
默认shell是#!/bin/bash的shell环境执行shell脚本
shell脚本的运行
- 对脚本加上可执行权限直接运行
chmod 755 run.sh
./run.sh
2.通过 sh 命令执行shell脚本
sh ./run.sh
(二)输入/输出重定向
linux的三种输入输出:
stdin(标准输入),
stdout(标准输出),
stderr(标准错误输出)
输入重定向
输入重定向符号:<
例:cat命令即通过标准输入重定向到文件实现
输出重定向
输出重定向符: > and >>
“>” : 直接输出,当输出到文件中时,会覆盖之前的内容,对文件清空重写
“>>” : 附加输出,输出到文件中时以追加的方式添到文件中
(三)管道
管道:在一个命令的的标准输出和另一个命令的标准输入之间建立一个通道
例如:以下命令将ps -aux的结果进一步查询http显示出来
ps -aux | grep httpd
# ps 显示当前进程状态 缩写(process status)
# ps指令的选项:
# -A 列出所有的进程
# -w 显示加宽可以显示较多的资讯
# -au 显示较详细的资讯
# -aux 显示所有包含其他使用者的进程
# au(x) 输出格式 : USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
(四)Shell中的特殊字符
常见特殊字符
-
美元符号:$ 变量替换
-
反斜线:\ 转义字符
-
引号:
单引号 ‘’ 双引号 “” 倒引号 `
双引号扩起的内容,除了美元符号,倒引号,反斜线保留特殊作用外,其他均作为普通字符对待
单引号括起来的内容,均作为普通字符
倒引号括起来的的字符串被Shell解释为命令行,Shell会先执行该命令,然后将其结果取代倒引号部分
(五)Shell脚本的注释
注释方法:在注释行前加 “#”
例如:
#!/bin/sh
#这是注释
注意
第一行的注释 不仅作为注释,而且指明了脚本运行时使用的Shell
二.Shell变量
(一)系统变量
Shell 常用的系统变量
$# 命令行参数个数
$n $1表示第一个参数 $2表示第二个,以此类推
$0 当前程序的名称
$? 前一个命令或者函数的返回码
$* 以“参数1 参数2...”形式表示的所有参数
$@ 以“参数1” “参数2”...
$$ 本程序的PID(进程号)
$! 上一个命令的PID(进程号)
Shell常用的系统变量
HOME 用于保存用户主目录的完全路径名。
PATH 用于保存用冒号分隔的目录路径名,shell将按PATH变量中给出的顺序搜索这些目录,找到的第一个与命令名称一致的可执行文件将被执行。
SHELL 当前用户使用的Shell
UID 当前用户的UID
LOGNAME 当前用户的登录名
HOSTNAME 主机名称
PS1 主命令提示符
PS2 二级命令提示符
PS3 select 的命令提示符
PS4 调试命令提示符
LD_LIBRARY_PATH 寻找库的路径,以冒号为分割
注意
也可以自定义环境变量,使用export命令
(二)用户变量
命名规则
- 变量名由数字,字母,下划线组成
- 不能以数字开头
- linux对大小写敏感
(三)变量的赋值与使用
变量的赋值和使用
- 变量无需声明,赋值即可使用,类似Python
- 赋值时等号两边不能由空格
- 使用变量:$+varible_name 特殊情况可使用${varible_name}
变量的重置
- 使用 unset 命令清空对变量的赋值
- 使用 readonly 变量将变量命名为常量(不可更改)
- 被 readonly 修饰的变量不能 unset
- shell的变量默认为全局变量,使用 local 命令声明局部变量
(四)数字和数组的声明
declare命令
- -i 定义整数 integer
- -a 定义数组 array
- -f 定义函数 function
- -r 定义为只读 readonly
- -x 定义为通过环境输出变量
数字的进制
declare -i num
num=2#110 # 将二进制的110赋值给num
num=8#775 # 将八进制的775赋值给num
数组的声明
declare -a array_name=(a b c)
# 使用:指定index
echo ${array_name[0]}
(五)Shell运算符
() []
! 否定 ~按位否定 ++增量 --减量 +正号 -符号
* / % 乘 除 取模
* - 加减
<< 左移 >> 右移
< <= > >= 小于 小于等于 大于 大于等于
== != 等等 不等
& 按位与
^ 按位异或
| 按位或
&& 逻辑与
|| 逻辑或
?: 条件
= += -= *= /= %= &= …… 赋值
, 逗号
三.Shell 流程控制
同其他语言,linux也由分支结构,循环结构的流程控制语句
分支结构
1.test命令
- test命令用于判断表达式并产生返回值
- test命令可以对整数,字符串,文件进行判断
- 格式:test expression 或者 [ expression ] (中括号和expression之间必须由空格)
整数
用于比较整数的关系运算符
-lt 小于 less than
-le 小于等于 less equal
-gt 大于 greater than
-ge 大于等于 greater equal
-eq 等于 equal
-ne 不等于 not equal
字符串
用于字符串的关系运算符
= 等于 此时有空格
!= 不等于
文件
用于文件的关系运算符
-f file 普通文件(不是目录或者设备文件)返回真
-s file 文件字节数大于0 返回真
-r file 文件存在且可读 返回真
-w file 文件存在且可写 返回真
-x file 文件存在且可执行 返回真
-d directory 目录存在且是目录 返回真
其他参数
-a 逻辑与(AND)
-o 逻辑或(OR)
! 逻辑非
\( \)分组扩号 扩起来的表达式之间有空格 \( expression \)
2.if命令
if语句结构
if [ expression ]
then [EXPRESSIONS]
fi
注意:if then fi 是独立语句,当写在一行时需要使用分号隔开
if/else 结构
if [ expression ]
elif then [ expression ]
elif then [ expression ]
......
else then [ expression ]
fi
3.case语句
case word in
conditon1) [ EPRESSIONS ] # conditionN分支条件
;;
condition2) [ EXPRESSIONS ]
;;
...
*) [ EXPRESSIONS ] # * 默认选项
;;
esac
循环结构
1.for语句
for NAME [ in LIST ]
do [ EXPRESSIONS ]
done
2.while语句
while CONTROL_COMMAND;
do [ EXPRESSIONS ];
done
3.until语句
until TEST_COMMAND;
do [ EXPRESSIONS ];
done
4.break --continue --exit语句
break: 正常结束循环之前退出循环
continue: 跳过本次循环,执行下一次循环
exit: 终止脚本并返回值,正常结束的程序返回0,异常结束返回1-255间的错误代码
四.Shell函数
声明Shell函数
# 方法一
function FUNCTION_NAME {
[ EXPRESSIONS ]
}
# 方法二
FUNCTION_NAME () {
[ EXPRESSIONS ]
}
Shell函数的调用
FUNCTION_NAME PARAMTER1 PARAMETER2 ......
Shell函数的递归调用
五.编写交互式脚本
交互脚本的优势
- 建立更加灵活的脚本
- 可自定义脚本使其在运行时产生不同的行为
- 脚本可以在运行时报告状态
(一)提示用户
echo转义字符序列
\a
\b
\c
\e
\f
\n
\r
\t
\v
\\
\ONNN 值为八进制的8比特字符
\NNN 值为八进制的8比特字符
\xHH 值为十六进制的8比特字符
echo常用选项
-e 解释转移字符
-n 禁止换行
接受用户输入
read命令
语法格式:
read [options] NAME1 NAME2 ...... NAMEN
read选项
-a ANAME 将输入读入ANAME数组
-d DELIM 截断输入字符,默认是换行符“\n”
-n NCHARS 读入n个字符
-p PROMPT 显示一个提示
-r 取消转义
-s 安静模式,输入的字符不显示
-T IMEOUT 超时,超时不输入read命令自动停止
练习
题目:编写一个shell脚本,计算100以内不是5的倍数的数字的和
#!/bin/bash
declare -i sum=0
for i in `seq 1 100`;
do
declare -i a=$[$i%5]
if [ $a -eq 0 ]
then
sum=$[$sum+$i]
fi
done
echo $sum
题目:编写一个shell脚本,自动将用户主目录下所有小于5kB的文件打包 tar.gz