一.shell脚本文件基础
集合一个或多个指令,按照指定的顺序执行的文件。
/etc/profile
系统设置用户的环境变量,当用户第一次登入时执行该文件配置环境变量
~/.bashrc
设置于个人用户有关的环境变量,打开终端时系统自动调用
文件创建
# 以.sh结尾
vim test.sh
选择解释器
# 文件开头添加
#!/bin/bash # 前面第一个#不是注释,要写
注释
# 单行注释
<<注释字符
多行注释
注释字符
# 注释内如果有`命令语句`,且命令语句有错误会报错,但因为不会执行没事
: ` # 注意加空格
多行注释
`
运行
# 脚本文件创建后一般没有执行权限
chmod 766 test.sh
./test.sh # 使用文本内解析器运行,在其他终端执行,将结果以字符串形式返回
bash test.sh # 先用指定bash解析,如果bsh不存在在使用默认解析器
. test.sh # 直接使用默认解析器
source test.sh # 等同 .
# windows下编写的脚本文件不能直接在linux下执行
# 需要
dos2unix test.sh
# 或在脚本末尾添加
:set ff=unix
命令分隔
一行内多行命令间加;
二.shell变量
定义/初始化
# 变量名=变量值
num=10 # 不要乱加空格
# shell中默认为字符串类型
# 若变量内容包含空格需要用使用单引号或双引号
只读变量
# readonly 变量名=值
readonly num=10
# 注意只读变量无法改变也无法(用unset)删除
变量命名规则
只包含英文字母数字下划线,不能以数字开头
引用
# $变量名
echo $num
# ${变量名}
echo ${num}
# 如果脚本执行中定义的变量于外部以及定义变量重名优先脚本中的变量
终端输入值
# read 变量名
read num
# 变量名未被定义则会自动定义
# read -p "显示信息" 变量名
# 输入时先输出提示信息
read -p "请输入num的值:" num
# 读取多个值
read num1 num2
# 123 abc # 两个值输入中间用空格隔开,不能用回车
# 输入的多余值赋给最后一个变量
# read -n num var
read -n 5 str
# 输入指定长度num的var,到达长度自动停止,过长会导致没有换行符
# num可以为变量$num
read -s var
# var输入时不显示内容
# read -t second var
# second秒未输入则跳过
read -t 3 var
字符串变量操作
str="hellow world"
echo ${#str} # 字符串长度 # 12 结尾没有\0
echo ${str:3} # 从下标3开始输出字符串 # low world
echo ${str:3:6} # 从下标3开始输出6个字符 # low wo # 中文算一个字符
echo ${str/l/L} # 将第一个l替换为L
echo ${str//l/L} # 将所有l替换为L
清除变量
# unset 变量名
unset num
系统预设变量
# shell提供无需用户定义
# 在脚本运行中无法更改
$# # 传给shell脚本参数的数量
$*;$@ # 传给shell脚本参数的所有内容(不含脚本名)
$1,$2,$3.. # 传给shell脚本的第n个参数
$? # 命令执行后返回的状态
$0 # 当前执行的进程名
$$ # 当前执行的进程号
# 给shell脚本传参
./test.sh 参数1 参数2...
$特殊使用
$() # 返回( )内命令输出
$(()) # 代表其内发送整数运算
$` ` # 返回` `内命令输出
${} # 依据字符分割选取字符串
“”,‘’,``,\,()与{}
# "" 内变量会被解释
# '' 内变量不会被解释
# `` 用在引号内,其中命令语句会被执行
# \ 转义字符,需要在echo后加选项-e
# () 其内填写命令语句,由子shell完成,不影响当前shell内的变量
# {} 期内填写命令语句,由当前shell执行,会影响当前shell内的变量
判断变量是否存在
echo ${num:-1}
# num存在输出num,不存在输出-1
三.shell数组
定义/初始化
# 只有一维数组
# 数组名=(成员列表)
arr=(1 2 3 4 5 6)
arr1=([0]=aa [2]=bb [1]=cc)
# 没有赋值的位认为为空
印用
${arr[num]} # 单独引用下标为num的数组成员
# 集体引用
${arr[@]}
${arr[*]} # [*]方法部分情况下所有成员整体会被视为一个长字符串
赋值
arr=([0]=9)
arr[0]=9
计算数组成员个数
echo ${#arr[@]}
echo ${#arr[*]}
计算单个成员长度
echo ${#arr[0]}
数组追加
arr=(${arr[*]} dd ee)
arr=(${arr[@]} dd ee)
# 单个成员内包含空格会被认定为两个成员(本质字符串)
arr=("${arr[@]}" dd ee)
# 可以避免单个成员内部空格的误判定
arr=("${arr[*]}" dd ee)
# 使用* 会导致源数组所有成员被认为一个成员
# 或者
arr[${#arr[@]}]=dd
数组清空
unset arr
从键盘输入值
read -a arr
# 给数组输入数据
read -p "arr:" -a arr
四.变量运算
因为shell内默认字符串,运算需要特定表示符
(())
var1=10
var2=20
var3=$(($var1+$var2))
var3=$((var1+var2))
((var3=var1+var2))
# 运算符前后可以加空格
# (())前要加$
# 自运算时不用加$
((var3++))
((++var3))
# ++性质于c语言相同
# 支持逗号运算符,最终值为最右表达式
# 变量=((表达1,表达2,表达3))
[]
var1=10
var2=20
var3=$[$var1+$var2]
var3=$[var1+var2]
# []内可以不加$
# []运算时必须有变量接收或者直接输出,否则报错
var4=$[var3=var1+var2]
# []内部不支持复杂运算
# 比如无法识别~为家目录
# 进行自加运算时,变量前不能加$
var4=[var3++]
# 支持逗号表达式
exper
var1=10
var2=20
expr $var1 + $var2 # 运算符两边要加空格,否则输出字符串
var3=`expr $var1 + $var2`
var3=`expr $var1 \* $var2` # 乘法符号需要转义
exper 字符串操作
var=hello
expr length $var # expr求字符串长度,字符串不能含有空格(其他选项同样要求)
# 查找字符位置
expr index $var "e" # 返回e,从1开始,返回最靠前的坐标6
# ""内如果是字符串多个字符,则返回""内字符串中出现在源字符串中最早的字符的下标
# 查找不到返回0
# 裁剪字符串
# expr substr $源字符串 起始下标 裁剪长度
expr substr $var 2 3
# 返回ell
# 字符串的匹配
# expr match $源字符串 "目标字符串"
expr match $var ".*ll"
# 从源字符串第一个字符开始匹配,有不同则返回0,相同则返回目标字符串长度
# "目标字符串"内是一个从头开始匹配的正则表达式
五.条件测试
test
# test [opt] [file]
test -e test.sh
# 或
[ -e test.sh ] # 注意 [] 内两边加空格
echo $?
# 是输出0 非输出1
文件测试
test -e file
# 选项不能一起使用 :-ed 的格式是禁止的
选项 | 含义 | 选项 | 含义 |
---|---|---|---|
-e | 是否存在 | -r | 是否可读 |
-s | 文件非空 | -w | 可写 |
-f | 是普通文件 | -x | 可执行 |
-S | 是套接字文件 | -L | 连接文件 |
-c | 是否字符设备 | -b | 是否块设备 |
-p | 是管道文件 | -d | 是目录 |
字符串测试
test $str1=$str2
test -n "str1"
# 判断非空串变量外要加"",所有字符串的操作都建议加""
选项 | 含义 | 选项 | 含义 |
---|---|---|---|
= | 两个字符串相等 | != | 两个字符串不相等 |
-z | 空串 | -n | 非空串 |
> | 大于 | < | 小于 |
数值测试
test num1 -gt num2
选项 | 含义 | 选项 | 含义 |
---|---|---|---|
-eq | 数值相等 | -ne | 数值不相等 |
-gt | 数1大于数2 | -ge | 数1大于等于数2 |
-lt | 数1小于数2 | -le | 数1小于等于数2 |
符合语句测试
test ! 1 -gt 5 -a ! 1 -gt 6
选项 | 含义 |
---|---|
-a | 两边情况同时成立 |
-o | 两状况任何一个成立 |
! | 相反状态 |
命令执行控制
&&
# 左边命令执行成功(返回0)shell才执行右边的命令
command1 && command2
||
# 左边的语句未执行成功(返回非0)shell才执行右边的命令
command1 || command2
六.控制语句
if
if [ 条件1 ];then # 注意[ ] 内两边加空格
# 也可以将[ ] 替换为test 语句
语句1 # if test -x file
elif [ 条件2 ];then
语句2
else
语句3
fi
case
case $变量名称 in
"变量内容1")
语句一
;; # 必须写,不支持case击穿
"变量内容2"|"变量内容2.2"|"变量内容2.3") # 匹配多个变量内容
语句二
;;
[0-9]|[a-z]) # [-] 表示范围
语句三
;;
[123456789]) # 字符列表,匹配列表其内单个字符
语句四
;;
[!ABC])
语句五
;; # !表示非,及匹配不在[]内的内容
*) # *) 部分可以不写
其他情况语句 # 从上向下匹配,位置会影响匹配结果
exit # *)写在最前会导致其他情况匹配不到
;;
esac
for
# 格式一
for((初始值;限制值;执行步阶)) # 注意是二重括号
do
语句
done
# 格式二
for((初始值;限制值;执行步阶)){
语句
}
# 格式三
for char in h e l l o # in 后跟字符列表
do # for var in {a..z} # var从a遍历到z
echo -n $char # for var in ${arr[@]} # 遍历数组成员
done
# 格式四
for filename in `ls .` # in 后跟指令
do
echo $filename
done
# 格式五
for var # var 遍历位置变量$1,$2,$3....
do
echo $var
done
while
while [ condition ]
do
语句
done
# 当condition内成立时进入循环
# 死循环 while [ 1 ] , while [ 0 ] , whil : , while [ 1==1 ]
until
until [ condition ]
do
语句
done
# 与while相反,condition成立则推出循环
select
select 变量 in 变量列表 # 注重交互的循环体
do
语句
done
# 执行到时会显示序号+变量列表,从终端输入序号,变量以对应选项值进行语句
# 一般与case连用
break
# 跳出循环
# break num 跳出num层循环,默认是1
break 2
continue
# 跳过本次循环
# continue num 跳过num层循环,默认是1
continue 2
# num 大于最外层循环是以最外循环层数算
sleep
# 睡眠
# sleep num # 睡眠num秒
sleep 3
七.函数
定义
# 格式1
函数名 ()
{
语句
}
# 格式2
function 函数名 ()
{
语句
}
# 函数必须在被使用前定义
# 函数内用特殊变量$1,$2,$3....
# $# 表示传入参数数量
# #@/* 显示所有参数
调用
# 函数名 参数1 参数2
add 1 2
# 可以用变量
add $num1 $num2
返回
return
# 提前结束函数
return 0 # 一般无错误的返回值
# return 返回数值在0-255内
# 超过255需要使用其他方法实现
add(){
sum=$(($1+$2))
return $sum
}
add 10 20
val=$?
全局变量
# shell中,变量属性默认全局变量
add(){
sum=$(($1+$2))
}
add 10 20
val=$sum
# 定义局部变量
local sum=$(($1+$2))
echo
add(){
sum=$(($1+$2))
echo $sum
}
val=`add 10 20`
分文件调用
fun.sh
function my_add() {
return $1+$2
}
main.sh
source fun.sh
my_add 1 2
echo $?