Shell编程

特殊变量

符号 描述
$0 当前程式的名字
$n 参数
$* 所有参数
$# 参数个数
$$ 当前程式的PID
$# 参数个数

Shell编程规范

  1. 赋值=左右不加空格
  2. 条件判断[ 值1 判断 值2 ]两端空格必须加

Shell配置文件加载顺序

  1. 所有xxx.sh文件执行前都会读取/etc/profile或者/etc/bashrc(Ubuntu)文件
    • 图形界面登录成功后打开终端先读取/etc/bashrc再读取~/.bashrc
    • 图形界面时先读取/etc/bashrc再读取~/.profile
  2. ~/.profile:3和6均不存在时读取该文件
    • 文本界面时先读取~/.profile再读取/etc/profile~/.bash_logout
  3. ~/.bash_profile
  4. ~/.bashrc:当bash以non-login形式执行时读取
  5. ~/.bash_logout:bash注销的时候读取
  6. ~/.bash_login:bash登录的时候读取

前后台作业控制

  1. fg %n: 将进程n切换到前台运行
  2. bg %n: 将进程n切换到后台运行
  3. kill -9 %n: 杀死进程n
  4. jobs:查看所有进程

输入输出重定向

文件描述符 文件名 类型 硬件
0 stdin 标准输入文件 键盘
1 stdout 标准输出文件 显示器
2 stderr 标准错误输出文件 显示器
  1. command > file以覆盖的方式将正确结果输出到文件
  2. command >> file以追加的方式将正确结果输出到文件
  3. command 2> file以覆盖的方式将错误结果输出到文件
  4. command 2>> file以覆盖的方式将错误结果输出到文件
  5. command > file 2>&1不分正确和错误输出所有到文件
  6. command &> file不分正确和错误输出所有到文件
  7. 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变量分类

  1. 自定义变量
    • 定义:
      • 直接赋值:var=value
      • 间接赋值:var='pwd'
    • 查看:echo $var
    • 删除:unset var(仅在当前控制台有效)
  2. 环境变量
    • 定义:
      • 直接定义:export var=value
      • 转义定义:export var(var为自定义变量)
  3. 位置变量
    • 命令的参数按位置排序依次为$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

流程控制

符号说明

  1. (())数值比较,运算,C语言
  2. [[]]条件测试,支持正则
  3. $(())$[]整数运算
  4. $()命令替换,将结果作为变量进行替换,错误输出不能替换
  5. ${}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

数组

定义方式

  1. array=(1 2 3)
  2. array=([0]=1 [1]=2 [2]=3)
  3. array[0]=1;array[1]=2;array[2]=3
  4. array=$(·ls /·)

遍历数组
echo ${array[@]}

数组中常用的变量

  1. 获取数组所有元素${array[*]}${array[@]}
  2. 获取数组的元素个数${#array[*]}${#array[@]}
  3. 获取指定下标的元素`${array[0]}
  4. 从下标x截取长度为y的数组${array[@]: x: y}
  5. 从下标x至末尾截取的数组${array[@]:x}
  6. 用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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!