一、变量与环境变量
- 获得字符串的长度
var=hello,world!
echo ${#var}
12
- 识别当前使用的 SHELL
echo $SHELL
或者
echo $0
- 检查是否为超级用户
if [ $UID -ne 0 ]; then
echo "Non root user.Please run as root."
else
echo "Root user."
fi
root 用户的 UID 等于0
注意
echo + 双引号和单引号的区别
单引号是原样输出,引号中的参数引用无效。
双引号会输出引号中的参数。
二、算术运算
整型计算
- let
let 可以直接支持基本算术操作
let a=b*c
let a++
let a--
let a+=1
let a-=1
- [ ] 操作符
a=$[ b + c ]
或
a=$[ $b + $c ]
- (( )) 操作符
a=$(( b + c ))
或
a=$(( $b + $c ))
- expr
a=`expr $b + $c`
或
a=$(expr $b + $c)
浮点计算
- bc
bc 是一个用于数学计算的高级工具
基本使用
a=`echo "$b * $c" | bc`
设置小数精度
# 设置小数位为2
a=`echo "scale=2;$b * $c" | bc`
进制转换
a=100
echo "obase=2;$a" | bc
1100100
b=1100100
echo "obase=2;ibase=2;$b" | bc
100
平方和开平方
echo "sqrt(100)" | bc
echo "10^10" | bc
三、文件描述符与重定向
文件描述符是与某个打开的文件或数据流相关联的整数,是一种用户访问文件的抽象指示器。
- 0 stdin 标准输入
- 1 stdout 标准输出
- 2 stderr 标准错误
将标准输出和标准错误重定向到文件
command 1>stdout.log 2>stderr.log
将标准错误转换成标准输出,并重定向到文件
command 2>&1 file.log
或
command &> file.log
将标准输出 stdout 写入文件并且将副本作为后续命令标准输入
command | tee file.log | command
自定义文件描述符
0,1和2是stdin、stdout和stderr的预留描述符编号,我们可以使用exec
命令创建自定义的文件描述符。
创建一个文件描述符
echo hello,world! > file
exec 3<file
cat <&3
hello,world!
同理
exec 4>file
echo hello,world! >&4
cat file
hello,world!
exec 4>>file
echo hello,world! >&4
cat file
hello,world!hello,world!
注意,如果要再次读取和写入,需要用exec
重新分配文件描述符后才能使用。
四、数组和关联数组
数组
- 定义数组
arr=(a b c)
或者
arr[0]="a"
arr[1]="b"
arr[2]="c"
- 打印数组
echo ${arr[0]}
a
index=2
echo ${arr[$index]}
c
echo ${arr[*]} # 打印数组列表
a b c
echo ${arr[@]} # 打印数组列表
a b c
- 打印数组长度
echo ${#arr}
关联数组
- 声明并定义关联数组
declare -A ass_arr # 声明关联数组
ass_arr=([key1]=value1 [key2]=value2 [key3]=value3)
或者
ass_arr[key1]=value1
ass_arr[key2]=value2
ass_arr[key3]=value3
- 打印关联数组
echo "The string is $ass_arr[key1]"
The string is value1
- 列出关联数组所有索引
echo ${!ass_arr[*]}
或者
echo ${!ass_arr[@]}
五、函数和参数
- 定义函数
function function_name()
{
...
}
或者
function_name()
{
...
}
- 参数
fucntion function_name()
{
echo $0, $1, $2; # 脚本名 参数1 参数2
echo $@; # 以列表的方式一次性打印所有参数
echo $*; # 类似 $@ 但是参数被作为单个字符串,很少使用
return 0; # 返回值
}
六、命令输出写入变量
var=$(COMMANDS)
或者
var=`COMMANDS`
使用双引号可以保留空格和换行符(\n)
cat file
1
2
3
var=$(cat file)
1 2 3
var="$(cat file)"
1
2
3
七、标准输入
通过read
命令,从键盘或者标准输入中读取文本。
八、运行命令直至执行成功
- 定义一个函数
repeat()
{
while true
do
$@ && return
done
}
或
repeat() { while true; $@ && return; done }
- 一种更快的方法
":"命令是 Shell 内建的命令,它总是会返回0的退出码。而 true 是作为 /bin 中的一个二进制文件实现的,意味着每次 while 循环都会生成一个进程。
repeat()
{
while :
do
$@ && return
done
}
或
repeat() { while :; $@ && return; done }
- 增加延时
repeat()
{
while :
do
$@ && return
sleep 20 # 休眠20秒
done
}
或
repeat() { while :; $@ && return; sleep 20; done }
九、内部字段分隔符
内部字段分隔符(internal Field Separator, IFS)
- 实际演示
oldIFS=$IFS # 备份旧的IFS
IFS=","
for item in $items;
do
echo item: $item
done
IFS=$oldIFS
十、循环
- for
for item in items;
do
commands;
done
或
for((i=0; i<10; i++))
{
commands;
}
- while
while condition
do
commands;
done
- until
until condition
do
commands;
done
十一、判断
- if
if condition;
then
commands;
fi
- else if
if condition;
then
commands;
else if condition; then
commands;
else
commands;
fi
- 算数比较
单条件判断
[ $var -eq 0 ]
[ $var -ne 0 ]
多条件判断
[ $var -ne 0 -a $var -gt 2 ] # -a表示逻辑与
[ $var -ne 0 -o $var -gt 2 ] # -o表示逻辑或
- 文件系统测试
指令 | 含义 |
---|---|
[ -f $var ] | 判断文件路径或者文件名是否正确 |
[ -x $var ] | 判断文件是否可执行 |
[ -w $var ] | 判断文件是否可写 |
[ -r $var ] | 判断文件是否可读 |
[ -d $var ] | 判断是否为文件夹 |
[ -e $var ] | 判断文件是否存在 |
[ -c $var ] | 判断是否为一个字符设备文件的路径 |
[ -b $var ] | 判断是否为一个块设备文件的路径 |
[ -L $var ] | 判断是否为一个符号链接 |
- 字符串比较
使用字符串比较时,最好用双中括号 [[ ... ]]
,因为有时候采用单中括号会产生错误,最好避开它们。
[[ $str1 = $str2 ]] # 判断 str1 是否等于 str2
[[ $str1 == $str2 ]] # 判断 str1 是否等于 str2
[[ $str1 != $str2 ]] # 判断 str1 是否等于 str2
[[ $str > $str2 ]] # 判断 str1 的字母序是否大于 str2 字母序
[[ $str < $str2 ]] # 判断 str1 的字母序是否小于 str2 字母序
[[ -z $str ]] # str 为空返回真
[[ -n $str ]] # str 为非空返回真