注意点
通配符和正则表达式不同 特别是 * 这个符号 通配符:零到无限多个字符的意思 正则表达式:重复零到无限多个前一个字符的意思
${name} 取出变量结果 $(date) 在括号中执行命令,然后读取出命令结果,拿到它 `` 和上一个类似 $name 取出变量结果
echo "今天日期:$(date)"
数值计算
shell 的一些基础命令,只支持整数的运算,小数的计算需要如 bc 这样的命令
(( ))
echo $((3 + 4)) # 7
echo $((10 / 3)) # 3
echo $((5 ** 2)) # 25
echo $((3 < 4 && 5 == 5)) # 1
echo $((2 * 1.5)) # 报错
num=5
echo $((num = num * 3)) # 15
echo $num # 15
b=$((num = num * 3)) # b = 15
echo $((b++))
let
效果等同于双括号 效率更低一点
num=8
num=num+2 # echo $num --> num + 2
let num=num+2 # echo $num --> 10
expr
必须以参数的形式传递,所以要有空格 但是一些元字符有特殊含义,需要加转移字符
expr 5 \* 3 # 15
expr 5 + 3 # 8
expr length 123abc # 6
expr 5 \> 7 # 0
也可模式匹配 : 冒号,计算字符串的数量 .* 任意的字符重复 0 次或者多次 所以可用于 shell 脚本中判断后缀是否正确,因为不正确会返回 0
expr ycpng.png ":" ".*" # 6
expr ycpng.png ":" ".*p" # 7
expr ycpng.png ":" ".*png" # 9
name=ycpng.png
echo ${name#*png} # .png
# 注意区分正则表达式和变量删除替换的区别
bc
# 交互式
bc # 然后进入一个界面,自己输入数字和运算符即可,不用空格都行
# 管道符运用
echo "4.2*3" | bc # 12.6
echo "10/3" | bc # 3
echo {1..100} | tr " " "+" | bc # 5050
# 这个的语法是生成 1~100 序列,原本是空格,然后使用 tr 命令换成加号,然后利用管道符给 bc
seq -s "+" 100 | bc
# 这个语法同理,只是使用 seq,这个是生成序列,默认是一换行分隔,-s 更改分隔符
# 双括号
echo $((`seq -s "+" 100`))
# expr
seq -s " + " 100 | xargs expr
基础
#---------------------------------------------------------
##### if
# 注意括号内左右两边必须有空格
if [ num -ne 1 ]
then
执行体
elif 条件表达式
then
执行体
else
执行体
fi
# 也可这样
if 条件表达式; then
执行体
# ---------------------------------------------------------
###### case 语句
case $op in
"1" )
执行体
;;
"2" )
执行体
;;
"*" ) #---------> 都没匹配上,执行这个,类似于 C++ default
执行体
;;
esac
# ---------------------------------------------------
##### while 循环
while [ 条件判断式 ]
do
执行体
done
# for 循环
for str in I am a handsome boy
do
执行体
done
s=0
for (( i=1; i<=10; i++ ))
do
s=$(( $s+$i ))
done
echo $s # 55
#--------------------------------------------------------------
####### 函数
# function 关键字可省略
function func(){
执行体
return 返回值 # $? 状态码
}
# 调用
func
# 函数里定义的变量为局部变量
# return 是结束函数运行,返回一个值,给脚本
# exit 是结束 shell 环境,返回一个值为当前的 shell
# return 只能写在函数里
# 函数内,用 local 定义局部变量
function func(){
echo ok
echo no
return 0
}
func
# 函数单独写在一个文件里,需要用 source 读取
# 在一个 bash 文件中写这段代码,只定义,不执行
# 调用 source 或者 . 命令,能够加载当前函数到当前 shell 环境中
# 然后直接调用函数就能执行,但是是临时的,重新进入当前 shell,环境中的这个函数不存在
function func(){
echo ok
echo no
return 0
}
# 传参
function func(){
echo $1
echo $2
return 0
}
func $1 $2
# 执行
bash a.sh "a" "b"
条件测试
在这里的运用 || 和 && 这符号有所区别 && 是指前者成功,也执行后者;前者失败,都不执行 || 是指前者失败,执行后者,前者成功,不执行后者
test
# 语法:test -e filename
-e 该文件是否存在(目录、文件、等等都能)
-f 该文件名是否为文件(file)
-d 该文件名是否为目录(directory)
-c 该文件名是否为一个 character device 装置
-s 该文件名是否为一个 Socket 文件
-p 该文件名是否为一个 FIFO(pipe)文件
-n 内容是否不为空,不空为 true
# 文件权限检测 test -r filename
-r 检测文件名是否具有可读的属性
-w 检测文件名是否具有可写的属性
-x 检测文件名是否具有可执行的属性
-u 检测文件名是否具有 SUID 的属性
-g 检测文件名是否具有 SGID的属性
-k 检测文件名是否具有 Sticky bit 属性
-s 检测文件名是否为非空白的文件
# 两个整数之间的判定,例如 test n1 -eq n2
-eq 两数值相等(equal)
-ne 两数值不等(not equal)
-gt n1 大于 n2(greater than)
-lt n1 小于 n2(less than)
-ge n1 大于等于 n2(greater than or equal)
-le n1 小于等于 n2()less than or equa1)
# 多重判定
-a 两状况同时成立!例如 test -r file -a -x file,则 file 同时具有 r 和 x 权限时,才回传 true
-o 两状况任何一个成立
! 反向状态,如 test ! -x file,当 file 不具有 x 时,返回 true
# 判断两字符串数据
test -z string 判定字符串是否为 0 ?若 string 为空字符串,则为 true
test -n string 判定字符串是否为 非0 ?若 string 为空字符串,则为 false。
注:-n 亦可省略
test str1 = str2 判定 str1 是否等于 str2 ,若相等,则回传 true
test str1 != str2 判定 str1 是否不等于 str2 ,若相等,则回传 false
中括号
作用和 test 一样 和 if 一样,需要左右两边加空格
[ -f "$filename" ] # 注意这里需要加双引号,条件测试里,都需要
[ -f "$filename" ] && echo ok # 和 test 参数一致,使用同理
双中括号
[[ 条件判断 ]]
# 验证文件是否有对应的权限
# 注意:root 需要排除,都具有权限
各种比较逻辑
# 字符串比较
# 符号前后需要空格
== 判断是否相等
!= 判断是不等的
! 去结果的反义
# 示例
name="hh"
[ "$name" == "hh" ] && echo ok || echo no
[ ! -f filename ] && echo ok || echo no
# 数值比较
# test 中以及 [] 中,使用参数如 -ne
# 在 (()) 以及 [[]] 中使用 <= =或者==
[[ 1 < 2 ]] && echo ok || echo no # ok
[ 1 \< 2 ] && echo ok || echo no # 如果使用 [] 需要使用转义字符
[ 1 -lt 2 ] && echo ok || echo no # ok
[[ 1 -lt 2 ]] && echo ok || echo no # ok
# 逻辑运算符
# test 和 [] 中使用 -a, -o !,在 [[]] 和 (()) 使用 && || !