概述
本文最初写于2021/03/11,遇到新技巧会不定期更新
- 2021/07/13更新:增加使用案例
…
查看机器支持的脚本
cat /etc/shells
基础
# bash脚本一般以下面这句开头,也就是指定shell脚本的解析器为bash的意思
#!/bin/bash
字符串
拼接字符串
# 如果需要变量和字符串拼接就用这种最原始的方式就好了,需要注意的是,如果字符串中有变量,不能是用哪个单引号,必须使用双引号
"hello worl $1"
str1="123"
str2="456"
echo $str1$str2
# 下面这种方式也可以实现字符串拼接的效果
echo $str3"000"
# 系统函数与字符串拼接。date是一个系统函数,需要使用反引号引起来
echo "[`date`]"
# 命令与命令拼接
echo `date``ls`
按空格分隔字符串
str="a b c d e"
arr=($str) #外层包一个括号表示按空格分隔字符串
echo $arr # 会输出数组的第一个元素,相当于${arr[0]},注意这个$是必须的
echo ${arr[1]} #输出数组中的第二个元素
变量
常用系统变量
系统变量需要以$
开头
$HOME # 当前用户的home路径
$PWD #当前路径
$SHELL #当前用的bash解析器
自定义变量
用户自定义变量不需要指定类型,直接复制即可。
- 在bash中,变量默认是字符串类型,无法直接进行数值运算。
- 如果变量有空格,需要使用单引号或者双引号引起来。
- 使用
export
关键字可以将普通变量提示为全局变量。比如在.bash_profile
文件中写的变量我们都export
了,这样是为了将其提示为全局变量。
#定义一个变量A并赋值,注意等号左右两边必须没有空格
A=2
echo $A #输出A的值
# 撤销变量赋值,执行下面语句以后,再echo $A,不会有任何输出
unset A
# 定义一个静态变量(只读变量),只读变量不能执行unset命令
readonly B=9
C=1+1
echo $C #这里会输出1+1,而不是输出2
特殊变量:$n
n表示数字。$0代表该脚本的名称,$1- 9 代 表 第 1 到 第 9 个 参 数 。 10 以 上 的 参 数 需 要 写 大 括 号 , 如 9代表第1到第9个参数。10以上的参数需要写大括号,如 9代表第1到第9个参数。10以上的参数需要写大括号,如{10}。
特殊变量:$#
获取所有输入参数的个数,通常用于循环。个数中不包含第0个参数。
特殊变量:$*
和$@
前者代表命令行中所有参数。这些参数被看成一个整体。
后者代表命令行中所有参数,但是把每个参数区分对待。
/test.sh 3 4 5 6 7
# 下面是$*/$#的输出,从样子上看一点区别都没有
3 4 5 6 7
3 4 5 6 7
特殊变量:$?
上一条命令的返回状态,如果这个变量输出为0,表示上一条命令执行成功,如果为非0则表示上一条命令执行失败。
# 比如在脚本中或者在命令行中执行下面命令,会返回0
echo 'hello world'
echo $?
运算符
- 数字运算需要使用
expr
关键字,如expr 2 + 3
,expr和运算符直接都要有空格,如果2+3没有空格就不能输出计算结果 $((运算式))
或者$[运算式]
- +、-、
\*
、\分别对应加减乘除
# 计算2+3*4
expr `expr 2 + 3` \* 4
# 可以使用中括号的方式执行
s=$[(2+3)*4]
条件判断
[ 条件 ]
条件的左右两边要有空格。非空即判断为true,[]
才会判断为false。注意这个条件判断可以理解为是一条语句,不一定要写在if后面。
通常=
用于字符串直接的判断。如果是两个数判断,使用-eq
判断是否相等
-lt # less than 小于
-le # less equal 小于等于
-eq # equal 等于判断
-gt # greater than 大于
-ge # greater equal 大于等于
-ne # 不等于
按照文件权限判断
-r # 有读权限
-w # 有写权限
-x # 有执行权限
按文件类型判断
-f # 文件存在,并且是一个常规文件
-e # 文件存在
-d # 文件存在并且是一个目录
其他判断
-z [变量值] #如果变量值为空,则条件为true,如果不为空则条件为false
#!/bin/bash
if [ -z "$1" ]; then # 执行这个脚本,如果传值,这么这个条件就进不去了,注意变量需要使用双引号引起来,不写有些解释器解析不出来
echo $1
echo 'I am in.'
fi
echo 'hello world'
-n [变量值] #与上面相反,如果变量值非空为true,否则为false
#!/bin/bash
if [ -n "$1" ]; then
echo $1
echo 'I am in.'
fi
echo 'hello world'
操作
[ 23 -ge 24 ] # 判断23是否大于等于24
echo $? # 如果上面条件成立,这里输出0,否则输出1
[ -d test.sh ] # 判断test.sh是否是目录
流程控制表达式
if表达式
# 下面脚本表示如果输入的是1,输出1111,如果输入的是2,输出222
#!/bin/bash
if [ $1 -eq 1 ]; then # 注意这里有分号,中括号中左右要有空格
echo '1111'
elif [ $1 -eq 2 ]; then
echo '222'
fi
case表达式
#!/bin/bash
case $1 in #这一行必须要以in关键字结尾
1) #这里表示如果输入的值为1,则只需下面的语句
echo "1"
;; #这里两个分号表示这个分支的结束
2)
echo "2"
;;
*) # 星号就是default的意思。
echo "3"
;;
esac
for循环
累加100以内的值并输出。
#!/bin/bash
s=0
for ((i=1;i<=100;i++))
do
s=$[$s+$i]
echo $s
done
for循环还可以变量$*
中的值,这个特殊变量在前面讲过,表示所有输入的参数列表。
#!/bin/bash
for i in $*
do
echo ">> $i"
done
while循环
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s+$i] # 累加
i=$[$i+1] #i自增
done
echo $s
控制台输入
# t表示等待时间,如果超过9s,程序退出,-p表示提示信息,name表示输入的值要放到哪个变量中
read -t 9 -p "please enter your name" name
echo $name
常用系统函数
basename ~/myshell/read.sh # 输出read.sh,也就是输出文件名
dirname ~/myshell/read.sh # 输出/Users/yulei/myshell,也就是输出除文件名外的路径
dirname ~/myshell #输出的是/Users/yulei
date # 获取当前时间
案例
删除指定目录下,指定时间前的所有文件
#!/bin/bash
date_str=`date -d "60 days ago" +%Y-%m-%d`
echo $date_str
# deleting found files in /mnt/f/Mines
find /home/aspirin/TEST00001 -type f ! -newermt ${date_str} -exec rm -rf {} \;