一 shell基本概念
1.1 shell描述
shell是一个命令行解释器,它接受应用程序/用户的命令,然后操作Linux系统。
1.2 shell解析器
# 查看shell解析器
cat /etc/shells
# 指定shell脚本的解析器,必须放在第一行,默认使用 /bin/bash
#!/bin/bash
1.3 执行shell脚本
# 通过sh执行helloworld.sh脚本
sh helloworld.sh
# 通过bash执行helloworld.sh脚本
bash helloworld.sh
# 直接执行helloworld.sh脚本,需要可执行权限
./helloworld.sh # 相对路径
/tmp/helloworld.sh # 绝对路径
二 变量
2.1 自定义变量
# 定义变量A=1
A=1
# 定义只读变量,只读变量无法修改、撤销,系统重启后消失
readonly A=1
# 撤销变量
unset A
2.2 注意事项
- 变量名、等号、值三者之间不能有空格;
- 所有的变量都是字符串类型;
- 变量的值如果有空格,要用引号包起来;
2.3 使用变量
通过 $ 符号加上变量名。无论自定义变量还是系统变量。
2.4 全局变量
通过export,设置全局变量,在系统任何地方都可以使用。
export A=1
2.5 特殊变量
2.5.1 $n
n为从0开始整数,$0 表示该脚本名称,$1 开始表示传入脚本的第几个参数,从10开始的参数,数字要用大括号包起来,如 ${10}。
2.5.2 $#
获取脚本输入参数的个数。
2.5.3 $*
获取脚本所有的输入参数,用双引号包起来“$*”会把所有参数当做一个字符串。$*则是一个可遍历的列表。
2.5.4 $@
获取脚本所有的输入参数,$@和“$@”都是一个列表。可以遍历出来每个入参。
2.5.5 $?
获取上一条命令是否执行成功的结果。0为成功,非0为不成功。
三 运算
3.1 算术运算
3.1.1 运算符
- 加:+
- 减:-
- 乘:*,如果是通过expr计算,则是 \*
- 除:/
- 取余:%
3.1.2 运算表达式
计算三加二:
-
$[3+2]
-
$((3+2))
-
expr 3 + 2
# 计算2+3,然后乘以4 expr `expr 2 + 3` \* 4
注:expr计算中,运算符前后必须有空格。
3.2 逻辑运算
3.2.1 判断符
-
字符串:
- 是否相等:=
- 是否匹配正则:=~
-
数字:
-
小于:-lt
-
小于等于:-le
-
等于:-eq
-
大于等于:-ge
-
大于:-gt
-
不等于:-ne
-
-
文件权限:
- 读:-r
- 写:-w
- 执行:-x
-
文件类型:
- 是一个文件并且存在:-f
- 是一个文件夹并且存在:-d
- 文件或文件夹存在:-e
3.2.2 判断语法
[ 表达式 ]
[ a ]为true,[]为false
注:中括号中表达式两边必须有空格。
# 字符串判断
[ aaa = aaa ]
# 数字判断
[ 2 -gt 5 ]
# 文件权限判断
[ -r aaa.txt ]
3.2.3 逻辑运算符
- 与:&&
- 或:||
四 语句
4.1 判断语句
4.1.1 if判断
if [ 判断表达式 ];then
echo "a"
fi
if [ 判断表达式 ]
then
echo "a"
fi
if [ 判断表达式 ]
then
echo "a"
elif [ 判断表达式 ]
then
echo "b"
else
echo "c"
fi
注:if后面要有空格,判断条件的中括号内部两边要有空格。
4.1.2 case判断
#!/bin/bash
case $1 in
"1")
echo "1"
;;
"2")
echo "2"
;;
"3")
echo "3"
;;
*)
echo "*"
;;
esac
4.2 循环语句
4.2.1 for循环
#!/bin/bash
for ((i = 1; i < 5; i++))
do
echo $i
done
#!/bin/bash
s=0
for i in 1 2 3
do
s=$[$s+$i]
done
echo $s
4.2.2 while循环
#!/bin/bash
i=0
while [ $i -lt 10 ]
do
echo $i
i=$[$i+1]
done
4.3 读写语句
#!/bin/bash
read -t 10 -p "请在10秒内输入你的名字:" NAME
echo $NAME
4.3.1 读
read:读取用户在控制台输入的数据;
-t:表示等待用户输入的时间,单位:秒
-p:打印在控制台给用户的提示语句
4.3.2 写
echo:打印到控制台
echo 1 >> a.txt:把数字1追加写入文件a.txt
五 函数
5.1 系统函数
5.1.1 basename
basename函数会截取字符串中最后一个斜杠“/”之后的内容,还可以指定去掉后缀。
即从路径中获取文件名。
# 获取ccc.txt
basename /aaa/bbb/ccc.txt
# 获取ccc
basename /aaa/bbb/ccc.txt .txt
5.1.2 dirname
dirname函数会截取最后一个斜杠“/”之前的内容。
即获取路径中文件或文件夹的上级目录的路径。
5.2 自定义函数
和python一样,函数的声明必须在调用之前。
5.2.1 语法
#!/bin/bash
# 定义一个求和函数
function sun()
{
# 取函数第一个入参和第二个入参相加
s=$[$1+$2]
echo $s
}
# 调用函数
sun $1 $2
5.2.2 返回值
- 通过 echo 返回函数的返回值;
- 通过 $(调用函数) 获取echo的返回结果;
- 可以用return返回一个0-255之间的数字,返回的是函数中最后一行的执行状态(成功或失败);
- 通过$?获取函数return的返回值;
- 也可以不用return返回,则返回值为最后一条语句的执行结果。
六 常用工具
6.1 cut
将文件中每行数据按照指定分隔符分割后,取出指定列的数据。默认使用制表符分割。
# 根据制表符对文件aaa.txt中每行数据进行切割,取出第一、二、三列
cut -d " " -f 1,2,3 aaa.txt
# 取出环境变量中第二个冒号之后的内容
echo $PATH | cut -d : -f 3-
6.2 sed
sed是一个流编辑器。它一次处理一行数据,处理时,把当前处理的行存储在临时缓存区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容打印到屏幕接着处理下一行,直到文件末尾。
# 在文件ccc.txt的第二行插入内容aaa bbb
# 2表示第二行;a表示插入
# 不改变源文件ccc.txt数据
sed "2a aaa bbb" ccc.txt
# 去掉文件ccc.txt中包含aa的行
# d表示去掉
# 不改变源文件ccc.txt数据
sed "/aa/d" ccc.txt
# 将文件ccc.txt中的aa替换为bb
# s表示替换;g(global)表示全局,不需要是可以去掉
# 不改变源文件ccc.txt数据
sed "s/aa/bb/g" ccc.txt
# 删除文件ccc.txt中的第二行,并用aa替换为bb
# 2表示第二行;d表示删除;一个-e表示一次操作
sed -e "2d" -e "s/aa/bb/g" ccc.txt
6.3 awk
# 查找文件/etc/passwd中以root开头的行,然后用冒号:分割,取出第七列
awk -F : '/^root/ {print $7}' /etc/passwd
# 查找文件/etc/passwd中以root开头的行,然后用冒号:分割,取出第一和第七列,中间以逗号,分隔(默认空格分隔)
awk -F : '/^root/ {print $1","$7}' /etc/passwd
# 查找文件/etc/passwd以冒号:分割后的第一和第七列,最前面插入一行user,shell,最后面插入一行aaa,bbb
awk -F : 'BEGIN{print "user,shell"} {print $1","$7} END{print "aaa,bbb"}' /etc/passwd
# 定义一个变量i等于1,把文件/etc/passwd以冒号:分割后的第三列的值加上i即加一输出
awk -F : -v i=1 '{print $3+i}' /etc/passwd
# 获取文件名,当前行号,当前行被切割后的列数
awk -F : '{print "文件名:" FILENAME ",当前行号:" NR ",当前列数" NF}' /etc/passwd
6.4 sort
选项 | 功能 |
---|---|
-n | 根据数值的大小排序 |
-r | 倒序 |
-t | 指定分隔符 |
-k | 指定需要排序的列 |
# 将文件aaa.txt按照冒号:分割后,用第二列按照数值进行倒序排序
sort -t : -nrk 2 aaa.txt