一、符号介绍
$# | 脚本的参数个数 |
$* | 以一个单字符串显示所有脚本传递的参数 |
$$ | 当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态(或函数的返回值)。0表示没有错误 |
三、基础语法
echo --- 输出
echo "<输出信息>"
变量定义
# 私有变量定义 --- 只有当前脚本可以看到
<变量名>=<变量内容>
delcara <变量名>=<变量内容>
#用户环境变量定义
export <变量名>=<变量内容>
#数组定义
<变量名>=(
"成员1"
"成员2"
"..."
)
printf --- 输出
printf <格式化字符串> <参数>
格式指示符 | 描述 |
%b | 相对应的参数被视为含有要被处理的转义序列之字符串,见表:转义序列 |
%c | ASCII 字符 |
%d, %i | 十进制数 |
%e | 浮点格式 |
%E | 浮点格式 |
%f | 浮点格式 |
%g | %e或%f转换, 看哪一个较短,则删除结尾的零 |
%G | %E或%f转换, 看哪一个较短,则删除结尾的零 |
%o | 不带正负号的八进制值 |
%s | 字符串 |
%u | 不带正负号的十进制值 |
%x | 不带正负号的十六进制值,使用a至f表示10到15 |
%X | 不带正负号的十六进制值,使用A至F表示10到15 |
%% | 字面意义% |
转义序列 | 描述 |
\a | |
\b | |
\c | |
\f | |
\n | |
\r | |
\t | |
\v | |
\\ | |
\ddd | |
\0ddd | |
let --- 整数数学运算
let <运算表达式>
#!/bin/bash
let count=0
let count++
let a=${count}+1
echo "count=${count} a=${a}"

function --- 函数
返回值为整数
# 函数定义
[function] <函数名>() {
<入参1>=$1
<入参2>=$2
<入参n>=$n
<...>
return <整数返回值>
}
# 函数调用
<函数名> <参数1> <参数2> <...>
<函数返回值>=$?
函数相关符号 | 描述 |
$* | 以一个单字符串显示所有参数 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$0-$n | 函数的每一个参数,$0表示可执行程序本身,$1表示第一个参数 |
$? | 函数运行结果(返回值) |
$# | 参数个数 |
注:
不省略关键字 function 时,函数名后面的'()' 可以省略
省略关键字 function 时,函数名后面的'()' 不可以省略
#!/bin/bash
function cal_sum1() {
echo "cal_sum1 params: $@"
let sum=$1+$2
return $sum
}
cal_sum2() {
echo "cal_sum2 params: $*"
let sum=$1+$2
return $sum
}
cal_sum1 100 20
echo "sum1 100+20=$?"
cal_sum2 100 110
echo "sum2 100+110=$?"

返回值为字符串
# 函数定义
[function] <函数名>() {
<入参1>=$1
<入参2>=$2
<入参n>=$n
<...>
echo "<字符串>"
}
# 函数调用
<返回值变量>=$(<函数名> <参数1> <参数2> <...>)
注:此处获取到返回值,永远是函数中第一个echo输出的字符串
#!/bin/bash
function test_func() {
echo "$1"
echo "is return val ?"
}
result=$(test_func "hello world")
echo "test_func return val=$result"

函数入参为数组
# 函数定义
[function] <函数名>() {
<数组入参>=$1
<入参2>=$2
<入参n>=$n
for <成员变量> in ${数组入参[@]}
do
<...>
echo "element=${成员变量}"
done
return <整数返回值>
}
<数组变量名>=(
"成员1"
"成员2"
"..."
)
# 函数调用
<函数名> "${数组变量名[*]}" <参数2> <...>
<函数返回值>=$?
#!/bin/bash
function test_func() {
list=$1
for student in ${list[@]}
do
echo ${student}
done
}
student_list=(
"xiaoming"
"zhangsang"
"xiaozhang"
)
test_func "${student_list[*]}"

if --- 条件判断
if [ <条件表达式> ]; then
<...>
elif [ <条件表达式> ]; then
<...>
else
<...>
fi
整数比较
if [ <整数> [选项] <整数> ]; then
<...>
fi
选项 | 描述 |
---|
-eq | 等于 |
-ne | 不等于 |
-gt | 大于 |
-ge | 大于等于 |
-lt | 小于 |
-le | 小于等于 |
字符串比较
if [ "<字符串1>" [选项] "<字符串1>" ]; then
<...>
fi
选项 | 描述 |
== 或 = | 两个字符串相等 |
!= | 两个字符串不相等 |
< | 字符串1 字典排序在 字符串2前面 |
> | 字符串1 字典排序在 字符串2后面 |
字符串判断
if [ [选项] "<字符串>" ]; then
<...>
fi
选项 | 描述 |
-n | 字符串长度非0,则为真, 也即字符串不为空。-n 可缺省 |
-z | 字符串长度为0,则为真, 也即字符串为空。-z 不可缺省 |
文件判断
if [ [选项] <文件或目录> ]; then
<...>
fi
选项 | 描述 |
-a | 文件存在则为真 |
-d | 文件为目录且存在为真 |
-e | 文件或目录存在时为真 |
-f | 文件存在且为一个普通文件则为真 |
-r | 文件存在且具有可读权限则为真 |
-w | 文件存在且具有可写权限则为真 |
-x | 文件存在且具有可执行权限则为真 |
-b | 文件存在且是一个块文件则为真 |
-c | 文件存在且是一个字符文件则为真 |
-g | 文件存在且设置了SGID则为真 |
-h | 文件存在且是一个符号符号链接文件则返回为真 |
-k | 文件存在且已经设置了冒险位则返回为真 |
-p | 文件存并且是命令管道时返回为真 |
-s | 文件存在且大小非0时为真则返回为真 |
-u | 文件存在且设置了SUID位时返回为真 |
-O | 文件存在且属有效用户ID则返回为真 |
-G | 文件存在且默认组为当前组则返回为真 |
-L | 文件存在且是一个符号连接则返回为真 |
-N | 文件存在 and has been mod如果ied since it was last read则返回为真 |
-S | 文件存在且是一个套接字则返回为真 |
文件比较
if [ <文件1> [选项] <文件2> ]; then
<...>
fi
选项 | 描述 |
-nt | 如果 文件1 比 文件2 新, 或者 文件1 存在但是 文件2 不存在则返回为真 |
-ot | 如果 文件1 比 文件2 老, 或者 文件2 存在但是 文件1 不存在则返回为真 |
-ef | 如果 文件1 和 文件2 指向相同的设备和节点号则返回为真 |
逻辑判断
if [ ! <表达式> ]; then
<...>
fi
if [ <表达式> -a <表达式> ]; then
<...>
fi
if [ <表达式> ] && [ <表达式> ]; then
<...>
fi
if [ <表达式> -a <表达式> ]; then
<...>
fi
if [ <表达式> ] || [ <表达式> ]; then
<...>
fi
高级特性
数学表达式 --- (())
# 双圆括号(( )):表示数学表达式
# 在判断命令中只允许在比较中进行简单的算术操作,而双圆括号提供更多的数学符号,
# 而且在双圆括号里面的'>','<'号不需要转意。
if (( <数字> [运算符] <数字> ))
运算符 | 含义 |
> | 大于 |
>= | 大于等于 |
< | 小于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
高级字符串处理 --- [[]]
# 双方括号[[ ]]:表示高级字符串处理函数
# 双方括号中判断命令使用标准的字符串比较,还可以使用匹配模式,
# 从而定义与字符串相匹配的正则表达式。
if [[ <字符串> [运算符] <字符串> [逻辑运算符] <字符串> [运算符] <字符串> ]]
if [[ [运算符] <文件或目录> [逻辑运算符] [运算符] <文件或目录> ]]
运算符 | 含义 |
= | 两个字符串相等 |
!= | 两个字符串不相等 |
-n | 字符串长度非0,则为真, 也即字符串不为空。-n 可缺省 |
-z | 字符串长度为0,则为真, 也即字符串为空。-z 不可缺省 |
-r | 文件存在且具有可读权限则为真 |
-l | 文件存在且是一个符号连接则返回为真 |
-w | 文件存在且具有可写权限则为真 |
-x | 文件存在且具有可执行权限则为真 |
-f | 文件存在且为一个普通文件则为真 |
-d | 文件为目录且存在为真 |
-s | 文件存在且大小非0时为真则返回为真 |
-nt | 如果 文件1 比 文件2 新, 或者 文件1 存在但是 文件2 不存在则返回为真 |
-ot | 如果 文件1 比 文件2 老, 或者 文件2 存在但是 文件1 不存在则返回为真 |
! | 逻辑非 |
&& | 逻辑与 |
|| | 逻辑或 |
for --- 循环
<数组名>=(
<"...">
)
for <变量> in ${<数组名>[@]}
do
if [ <表达式> ]; then
<...>
continue
fi
<...>
break
done
或
for ((<赋值表达式>; <条件表达式>; <循环表达式>))
do
if [ <表达式> ]; then
<...>
continue
fi
<...>
break
done
array=(
"xiaoming"
"zhangsan"
)
for i in ${array[@]}
do
echo $i
done
for (( i=1; i<3; i++ ))
do
echo $i
done

while --- 循环
while [ <表达式> ];
do
if [ <表达式> ]; then
<...>
continue
fi
<...>
break
done
或
while [[ <表达式> ]];
do
if [ <表达式> ]; then
<...>
continue
fi
<...>
break
done
#!/bin/bash
let count=0
while [[ $count -le 5 ]];
do
echo $count
((count++))
done

until --- 表达式条件取反循环
until [ <表达式> ];
do
if [ <表达式> ]; then
<...>
continue
fi
<...>
break
done
或
until [[ <表达式> ]];
do
if [ <表达式> ]; then
<...>
continue
fi
<...>
break
done
#!/bin/bash
let count=8
until [[ $count -le 5 ]];
do
echo $count
((count--))
done

case --- 分支
case $<变量> in
<选项>)
<...>
break
;;
<...>)
<...>
break
;;
*)
<...>
break
esac
select --- 选择
<选项列表名>=(
<"选项">
<...>
)
PS3="提示信息:"
select <变量> in ${<选项列表名>[@]};
do
<...>
break;
done
// select和case结合
select_list=(
"xiaoming"
"xiaozhang"
)
PS3="Please select a student:"
select args in ${select_list[@]}
do
case $args in
"xiaoming")
echo "student is xiaoming"
break
;;
"xiaozhang")
echo "student is xiaozhang"
break
;;
*)
break
esac
done

四、常用命令介绍
read --- 读取
read [选项] <输入>
选项 | 说明 |
-a | 限定输入为数组 |
-d <结束符号> | 指定结束符,遇到该字符是立即结束 |
-e | 使用readline处理输入,允许使用和命令行相同的方式编辑输入 |
-i <文本> | 如果用户直接按Enter键,使用文本作为默认值,需要配合-e选项使用 |
-n <num> | 从输入中读取num个字符,而非读取一整行 |
-N <num> | 只在准确读取num个字符后返回,除非遇到EOF或读取超时,忽略任何分隔符。 |
-p <"提示信息:"> | 指定输出提示信息 |
-r | 反斜杠转义不会生效,意味着行末的’\’成为有效的字符,例如使 \n 成为有效字符而不是换行 |
-s | 不显示输入的值,一般用于密码 |
-t <timeout> | 指定超时时间,单位:秒 |
-u fd | 从文件描述符fd中读取输入 |
从标准输入读取内容
read -p <"提示信息"> <变量>
#!/bin/bash
read -p "请输入:" input
echo $input

读取文件内容
while 循环法
while read [选项] <变量>
do
# 默认每次从文件中读取一整行,也可以通过read支持的选项改变默认行为
<...>
done < <文件>
文件描述符法
Exec 3<&0 # 将所有内容重定向到文件描述符3来关闭文件描述0
Exec 0<<文件> # 将输入文件放到文件描述符0
while read [选项] <变量>
do
# 默认每次从文件中读取一整行,也可以通过read支持的选项改变默认行为
<...>
done