Shell编程
特殊变量
符号 | 描述 |
---|---|
$0 | 当前程式的名字 |
$n | 参数 |
$* | 所有参数 |
$# | 参数个数 |
$$ | 当前程式的PID |
$# | 参数个数 |
Shell编程规范
- 赋值
=
左右不加空格 - 条件判断
[ 值1 判断 值2 ]
两端空格必须加
Shell配置文件加载顺序
- 所有
xxx.sh
文件执行前都会读取/etc/profile
或者/etc/bashrc
(Ubuntu)文件
- 图形界面登录成功后打开终端先读取
/etc/bashrc
再读取~/.bashrc
- 图形界面时先读取
/etc/bashrc
再读取~/.profile
~/.profile
:3和6均不存在时读取该文件
- 文本界面时先读取
~/.profile
再读取/etc/profile
和~/.bash_logout
~/.bash_profile
~/.bashrc
:当bash以non-login形式执行时读取~/.bash_logout
:bash注销的时候读取~/.bash_login
:bash登录的时候读取
前后台作业控制
- fg %n: 将进程n切换到前台运行
- bg %n: 将进程n切换到后台运行
- kill -9 %n: 杀死进程n
- jobs:查看所有进程
输入输出重定向
文件描述符 | 文件名 | 类型 | 硬件 |
---|---|---|---|
0 | stdin | 标准输入文件 | 键盘 |
1 | stdout | 标准输出文件 | 显示器 |
2 | stderr | 标准错误输出文件 | 显示器 |
command > file
以覆盖的方式将正确结果输出到文件command >> file
以追加的方式将正确结果输出到文件command 2> file
以覆盖的方式将错误结果输出到文件command 2>> file
以覆盖的方式将错误结果输出到文件command > file 2>&1
不分正确和错误输出所有到文件command &> file
不分正确和错误输出所有到文件command > file1 2> file2
分别输出正确和错误结果到不同的文件
wc -l << ENDD
> 1
> 222
> 3334334
> ENDD
3
command | tee file
将结果输出的同时保存到文件command1 | command2
将1的结果作为2的输入输出
# 字体颜色:30m-37m 黑、红、绿、黄、蓝、紫、青、白 echo -e "\033[30m string \033[0m" # 背景颜色:40-47 黑、红、绿、黄、蓝、紫、青、白 echo -e "\033[41;37m string \033[0m" # 获取var的字符串长度 echo ${#var} # 运算:+(加) -(减) \*(乘) /(除) echo $[5**2] #等同于expr 5**2 # 格式化输出 scale(小数位数) ibase/obase(进制) echo "scale=2;4/3" |bc # 索引和切片 var = hello,world! echo ${var5} #结果:hello echo ${var:5} #结果:,world! # 匹配输出 var = hello,world! echo ${var#*o} #结果:,world! echo ${var##*o} #结果:rld! echo ${test/o/O} #结果:hellO,world! echo ${test//o/O} #结果:hellO,wOrld!
Shell变量分类
- 自定义变量
- 定义:
- 直接赋值:
var=value
- 间接赋值:
var='pwd'
- 直接赋值:
- 查看:
echo $var
- 删除:
unset var
(仅在当前控制台有效)
- 定义:
- 环境变量
- 定义:
- 直接定义:
export var=value
- 转义定义:
export var
(var为自定义变量)
- 直接定义:
- 定义:
- 位置变量
- 命令的参数按位置排序依次为
$1-~
- 所有参数为
$*
- 参数个数为
$#
- 进程PID为`$$
- 命令的参数按位置排序依次为
Read输入
计算和
read -p "请输入NUM1:" num1 read -p "请输入NUM2:" num2 echo -e "\033[31m $num1+$num2=$[$num1+$num2] \033[0m" read -u n #读取一次文件描述符n的内容,读取不到则停止
结果:
请输入NUM1:32
请输入NUM2:12
32+12=44
FOR循环
seq a b 用于产生a到b之间的所有整数(批量创建目录)
for i in {1..10} #等同于 for i in $(seq 1 10) do mkdir -p /home/calong/loop/demo$i done
遍历数组类变量(计算每个文件夹的大小)
DIR="/var" cd $DIR for i in $(ls $DIR) do [ -d $i ] && du -sh $i done
While循环
while循环读取文件内容
while read demo do echo $demo done < /home/calong/data/demo-3.txt
计算1-100以内的和
declare -i num=1 declare -i sum=0 while ((num<=100)) do let sum+=num let num++ done echo "和为:$sum"
Until循环
计算1-100以内的和
declare -i num=1 declare -i sum=0 until ((num>100)) do let sum+=num let num++ done echo "和为:$sum"
循环控制
break continue shift exit
while [ $# -gt 0 ] do echo $* shift done
运行结果
bash demo-6.sh a b c d e f a b c d e f b c d e f c d e f d e f e f f
流程控制
符号说明
(())
数值比较,运算,C语言[[]]
条件测试,支持正则$(())
和$[]
整数运算$()
命令替换,将结果作为变量进行替换,错误输出不能替换${}
Shell中的变量原型,限定变量名称的范围,支持通配符
&&
并且:前者成功再执行后者,否则不执行后者||
或者:前者执行失败时会执行后者,前者执行成功则不执行后者
文件测试表达式
命令 | 描述 |
---|---|
-d 文件 | 文件存在且为目录则为真 |
-f 文件 | 文件存在且为普通文件则为真 |
-e 文件 | 文件存在则为真 |
-s 文件 | 文件存在且大小不为0则为真 |
-r 文件 | 文件存在且可读则为真 |
-w 文件 | 文件存在且可写则为真 |
-x 文件 | 文件存在且可执行则为真 |
-L 文件 | 文件存在且为链接则为真 |
文件1 -nt 文件2 | 文件1比文件2新则为真 |
文件1 -ot 文件2 | 文件1比文件2旧则为真 |
字符串测试表达式
命令 | 参数 | 描述 |
---|---|---|
-z | string | 字符串长度为0则为真 |
-n | string | 字符串长度大于0则为真 |
sl | string | 字符串不为空则为真 |
= | string | 字符串相等则为真 |
!= | string | 字符串不相等则为真 |
< | string1 string2 | 字符串1按字典排序在字符串2之前则为真 |
> | string1 string2 | 字符串1按字典排序在字符串2之后则为真 |
整数操作符
命令 | 描述 |
---|---|
-eq | 等于 |
-nq | 不等于 |
-gt | 大于 |
-ge | 大于等于 |
-lt | 小于 |
-le | 小于等于 |
If判断
单分支if
if [ $USER=='root' ];then echo "当前为root用户" fi
双分支if
if [ $USER=='root' ];then echo "当前为root用户" else echo "当前为普通用户" fi
多分支if
read -p "请输入数字:" num if (( $num==0 ));then echo "零" elif (( $num>0 ));then echo "正数" elif (( $num<0 ));then echo "负数" else echo "不是数字" fi
case分支
read -p "请输入第几天:" day case $day in 1) echo "工作日" ;; 2) echo "工作日" ;; 3) echo "工作日" ;; 4) echo "工作日" ;; 5) echo "工作日" ;; 6) echo "周末" ;; 7) echo "周末" ;; *) echo "未知日期" ;; esac
数组
定义方式
- array=(1 2 3)
- array=([0]=1 [1]=2 [2]=3)
- array[0]=1;array[1]=2;array[2]=3
- array=$(·ls /·)
遍历数组
echo ${array[@]}
数组中常用的变量
- 获取数组所有元素
${array[*]}
和${array[@]}
- 获取数组的元素个数
${#array[*]}
和${#array[@]}
- 获取指定下标的元素`${array[0]}
- 从下标x截取长度为y的数组
${array[@]: x: y}
- 从下标x至末尾截取的数组
${array[@]:x}
- 用new替换数组中的值old
${array[@]/old/new}
联合数组
声明
declare -A assArray assArray=([name]=Tom [age]=18 [sex]=男)
输出
echo ${assArray[@]} #输出所有元素 echo ${assArray[name]} #输出指定元素 echo ${#assArray[@]} #输出元素个数
遍历
declare -A assArray assArray=([name]=Tom [age]=18 [sex]=男) for key in ${!assArray[@]} do echo "${key} => ${assArray[$key]}" done
并发
command #普通命令
{
command #开启进程执行命令
}&
wait #等待线程结束
command
并发控制
PRONUM=10 tmpfile="$$.fifo" #生成临时管道文件 mkfifo $tmpfile exec 6<>$tmpfile #以读写的方式生成文件标识符6 rm $tmpfile for ((i=0;i<$PRONUM;i++)) do echo >&6 #初始化线程 done for i in {1..100} do read -u 6 { ...... #需要并行的代码 echo >&8 #还回一条记录 }& done wait exec 8>&- #关闭文件描述符
正则表达式
字符 | 含义 |
---|---|
. | 匹配任意单个字符 |
^ | 匹配行首 |
$ | 匹配行尾 |
+ | 匹配前面正则表达式的1个或多个实例 |
? | 匹配前面正则表达式的0个或1个实例 |
[…] | 匹配范围,例如[a-z]/[0-9]/[a-z0-9] |
本作品采用《CC 协议》,转载必须注明作者和本文链接