shell基础教程
1. shell脚本
-
创建脚本 脚本内容:各种可以执行的命令
vim ./脚本名字
-
脚本使用
退推荐使用脚本执行命令 bash 脚本文件.sh
bash test.sh
2.变量
2.1 普通变量
普通变量的定义方式有如下三种,接下来我们就分别说一下这三种方式:数字不加引号,其他默认加双引号 方式一:
# 重点:变量值必须是一个整体,中间没有特殊字符
a=shell
方式二: 变量名='变量值'
# 重点:我看到的内容,我就输出什么内容
a='shell'
方式三: 变量名="变量值"
```
# 重点:如果变量值范围内,有可以解析的变量A,那么首先解析变量A,将A的结果和其他内容组合成一个整体,重新赋值给变量B
b="a=$a"
# 输出结果为 a=shell
```
2.2 命令变量
命令变量有两种定义方式,接下来我们就来介绍一下这两种方式 将命令执行后的结果,赋值给新的变量名a
# 方式一
a=`pwd`
# 方式二
a=$(pwd)
2.3 全局变量
在当前系统的所有环境下都能生效的变量
# 只显示全局变量
env
全局变量定义方式
方式一:
lla=$(ll -a)
export lla
方式二:
export lla=$(ll -a)
2.4 查看变量
方式一:
echo $lla
方式二:
$lla
方式三:
"$lla"
方式四: 推荐使用
"${lla}"
查看变量: ${变量名} 等价于 $变量名, 推荐使用${变量名}
2.5 取消变量
unset 变量名
2.6 内置变量
-
$0 当前执行脚本的文件名
-
$n n为1,2,3.... 执行脚本的参数,如果n大于9就要用大括号括起来${10}
-
$# 获取当前shell命令行中参数的总个数
-
$? 获取执行上一个指令的返回值(0为成功,非0为失败)
# 截取变量
file="fdslkfdsflkdfnkd.text"
${file:1:6} # 从第2个字符开始,截取5个字符
${file:0-6:3}从倒数第6个字符开始,截取之后的3个字符
默认值:
-
条件默认: ${变量名:-默认值}
-
强制默认: ${变量名+默认值}
2.表达式
2.1 条件表达式
方式一:
test 1=1
echo $?
# 结果输出 0
test 1=2
echo $?
# 结果输出 1
方式二:
[ 1=1 ]
echo $?
# 结果输出 0
[ 1=2 ]
echo $?
# 结果输出 1
2.2 逻辑表达式
&& ||
[ 1 = 1 ] && echo "条件成立" # 左边表达式成立时,右边才会执行
[ 1 = 2 ] || echo "条件成立" # 左边表达式不成立时,右边表达式才会执行
2.3 文件表达式
-f 判断输入内容是否是一个文件
[ -f weizhi.sh ] && echo "是一个文件"
# 是一个文件
[ -f weizhi.sddh ] || echo "不是一个文件"
不是一个文件
-d 判断输入内容是否是一个目录
[ -d weizhi.sddh ] || echo "不是一个目录"
# 不是一个目录
mkdir nihao
[ -d nihao ] && echo "是一个目录"
# 是一个目录
-x 判断输入内容是否可执行
[ -x age.sh ] || echo "文件没有执行权限"
# 文件没有执行权限
[ -x test.sh ] && echo "文件有执行权限"
# 文件有执行权限
2.4 数值操作符
-
-eq 相等
-
-gt 大于
-
-lt 小于
-
-ne 等于
2.5 字符串比较
str1 == str2 str1和str2字符串内容一致
str1 != str2 str1和str2字符串内容不一致,!表示相反的意思
2.6 计算表达式
计算格式
方式一:
$(( 计算表达式 ))
方式二:
let 计算表达式
注意:
$(())中只能用+-*/和()运算符,并且只能做整数运算
$(()) 的使用
a=10
echo $((2*a))
# 20
echo $((2*$a))
# 20
let 的使用
a=10
let b=a+10
echo $b
# 20
2.7 数组操作
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0
arr=(1 2 3 4)
echo ${arr[0]}
1 # 获取索引对应的 值
echo ${arr[@]}
1 2 3 4 # 获取数组中所有值
echo ${#arr[@]}
4 # 长度
echo ${!arr[@]}
0 1 2 3 # 获取所有索引下标
# @等价于* 可替换
增删改查
arr=(1 2 3 4)
增:
arr[4]=5
echo ${arr[*]}
1 2 3 4 5
删:
unset arr[0]
echo ${arr[*]}
2 3 4 5
unset arr # 删除数组
改:
修改下标对应的值
arr=(0 1 2 3)
arr[0]=1
echo ${arr[*]}
1 1 2 3
查:
通过索引
echo ${arr[0]}
3.命令符号
& 将一个命令从前台转到后台执行
sleep 5 &
转为后台执行
信息符号
符号详解:
1 表示正确输出的信息
2 表示错误输出的信息
2>&1 代表所有输出的信息
4.简单流程控制
4.1 if语句
格式:
if [ 条件 ]
then
指令1
elif [ 条件2 ]
then
指令2
else
指令3
fi
4.2 case语句
格式:
case 变量名 in
值1)
指令1
;;
...
值n)
指令n
;;
esac
4.3 循环语句
4.3.1 for语句
格式:
for 值 in 列表
do
执行语句
done
例子:
for i in $(ls ./personal_blog)
do
echo "/personal_blog 中有文件 ${i}"
done
4.3.2 while语句
条件满足时,执行循环
格式:
条件满足时,执行循环
while 条件
do
执行语句
done
实例:
a=1
while [ ${a} -lt 5 ]
do
let a=a+1
echo "${a}"
done
4.3.3 until语句
满足条件时退出循环
格式:
注: 满足条件时退出循环
until 条件
do
执行语句
done
实例:
# until 循环
a=1
until [ ${a} -eq 5 ]
do
let a=a+1 # 等价于 a=$((a+1))
echo "${a}"
done
4.3.4 循环退出
break 跳出所有循环
break n 跳出第n个循环(由内向外)
continue 跳出当前循环
exit 退出程序
-
break 实例
while :
do
echo -n "请输入范围在1-6的数字:"
read num
case "${num}" in
1|2|3|4|5|6)
echo "你输入的数字是:${num}"
break
;;
*)
echo "输入的数字错误,请重新输入"
esac
done
-
break n 实例
for i in {1..5}
do
for j in {0..4}
do
if [ ${i} -eq 2 -a ${j} -eq 0 ]
then
echo "${i}${j}"
break 1 # 从内往外 跳出1个循环
else
echo "${i}${j}"
fi
done
echo "${i}"
done
-
continue 实例
for i in {1..5}
do
for j in {0..4}
do
if [ ${i} -eq 2 -a ${j} -eq 0 ]
then
echo "${i}${j}"
continue # 跳出当前循环
else
echo "${i}${j}"
fi
done
echo "${i}"
done
5.复杂流程控制-函数
5.1 函数定义
函数就是将某些命令组合起来实现某一特殊功能的方式,是脚本编写中非常重要的一部分。
#!/bin/bash
# 函数使用场景一:执行频繁的命令
# 先定义函数
fn(){
echo "hello world"
}
# 调用函数
fn
###################################
# 传参使用
fn(){
# $1, $2,.... 获取的是函数传入的参数
a=$1
echo "你好, 我是${a}"
}
# 调用函数
fn 张三
fn 李四
5.2 函数的使用
5.2.1 脚本传参和函数传参
#!/bin/bash
###################################
# 传参使用
fn(){
# $1, $2,.... 获取的是函数传入的参数
a=$1
echo "你好, 我是${a}"
}
# 获取脚本参数
a=$1
# 调用函数
fn "${a}"
生产脚本使用:
#!/bin/bash
###################################
# 获取脚本传入的参数
a="$1"
# 传参使用
fn(){
# 获取函数传入的参数
echo "你好, 我是$1"
}
# 调用函数
fn "${a}"
6.常见命令详解
6.1 grep命令详解
命令格式grep [参数] [关键字] <文件名>
注意:我们在查看某个文件的内容的时候,是需要有<文件名>
grep命令在结合 | (管道符) 使用的情况下,后面的<文件名>是没有的
可以通过 grep --help 查看grep的帮助信息
参数详解
-c:只输出匹配行的计数。
-n:显示匹配行及行号。
-v:显示不包含匹配文本的所有行。
6.2 sed命令详解
格式详解
sed 行文件编辑工具。因为它编辑文件是以行为单位的。
命令格式:
sed [参数] '<匹配条件> [动作]' [文件名]
注意:可以通过 sed --help 查看帮助信息
参数详解:
参数为空 表示sed的操作效果,实际上不对文件进行编辑
-n 取消静默输出-i 表示对文件进行编辑
注意:mac版本的bash中使用 -i参数,必须在后面单独加个东西: -i ''
匹配条件:
匹配条件分为两种:数字行号或者关键字匹配关键字匹配格式:'/关键字/'
注意:隔离符号 / 可以更换成 @、#、!等符号根据情况使用,如果关键字和隔离符号有冲突,就更换成其他的符号即可。
动作详解
a 在匹配到的内容下一行增加内容
i 在匹配到的内容当前行增加内容
d 删除匹配到的内容
s 替换匹配到的内容
p 查看指定内容
注意:
上面的动作应该在参数为-i的时候使用,不然的话不会有效果
# 查看指定内容
sed -n '2,6p' sed.txt # 查看第2~6行的内容
# 替换内容 隔离符号 / 可以更换成 @、#、!等符号
sed -i '2s/sed/SED/' sed.txt # 格式 sed -i '行号s/要替换的内容/替换后的内容/列号'
sed -i '2s/sed/SED/g' sed.txt # 全部替换
# 增加行
sed -i '2a\add_1' sed.txt # 在第2行之后添加一行
serd -i '2i\add_2' sed.txt # 在第2行之前添加一行
# 删除行或内容
sed -i '2d' sed.txt # 删除第2行
sed -i '2,5d' sed.txt # 删除第2,3,4,5行
sed -i '/待删除的内容/d' sed.txt # 删除指定内容
6.3 awk命令详解
格式详解awk是一个功能非常强大的文档编辑工具,它不仅能以行为单位还能以列为单位处理文件。
命令格式:awk [参数] '[ 动作]' [文件名]
常见参数:-F 指定列的分隔符-f 调用脚本-v 定义变量
常见动作:print 显示内容$0 显示当前行所有内容$n 显示当前行的第n列内容,如果存在多个$n,它们之间使用逗号(,)隔开
动作组成BEGIN{ 命令 } 初始代码块,主要和变量相关/pattern/{ 命令 } 匹配、执行代码块END{ 命令 } 结束代码块,主要和信息输出相关
内置变量FILENAME 当前输入文件的文件名,该变量是只读的NR 指定显示行的行号NF 输出 最大列数OFS 输出格式的列分隔符,缺省是空格FS 输入文件的列分融符,缺省是连续的空格和Tab
# 过滤包含nihao的内容
awk '/nihao/' awk.txt
# 打印第1列的数据
awk '{print $1}' awk.txt
# 打印内容时候,打印行号
awk '{print NR,$1}' awk.txt
# 查询
ls -l | awk '{if(($5 >= 500)) print NR " 文件名称:" $9 }
# 指定隔离分隔符,查看内容
awk -F ':' '{print $1,$2}' awk.txt
# -v参数 指定参数
echo | awk -v v1=100 -v v2=200 "{print v1,v2}"
echo | awk "{print v1,v2}" v1=100 -v v2=200
if语句示例
ls -l | awk '{if (($5>=500 && /^-/ )) print "\n" "文件: " $9 "\n" "大小: " $5 "B" "\n"}'
for语句示例
echo "abcde" | awk -F '' '{for(i=NF;i>=1;i--) print $i}'
6.4 find命令详解
格式详解
命令格式:find [路径] [参数] [关键字] [动作]
参数详解:-name 按照文件名查找文件。-user 按照文件属主来查找文件。-group 按照文件所属的组来查找文件。-type 查找某一类型的文件,
诸如:b - 块设备文件 d - 目录 c - 字符设备文件p - 管道文件 l - 符号链接文件 f - 普通文件。-size n(K|M|G):[c] 查找文件长度为n块的文件,带有c时表示文件长度以字节计。-perm (/|-)权限 按照文件权限来查找文件。 /表示有一个权限匹配即可,-表示相反权限匹配才可-mtime (-|+)n 查找n天数(内|外)修改的文件-ctime (-|+)n 查找n天数(内|外)改变的文件-atime (-|+)n 查找n天数(内|外)访问的文件-depth 在查找文件时,首先查找当前目录中的文件,然后再在其子目录中查找。-mindepth n 在查找文件时,查找当前目录中的第n层目录的文件,然后再在其子目录中查找。-path "子目录" 在指定目录的子目录下查找,一般与-prune使用-prune 在查找文件时,忽略指定的内容,不能和-depth共用,否则会自动忽视prune-newer 查找比指定文件新的文件! : 表示取反
动作详解:动作就表示,我们对查找出来的文件做进一步的操作,主要都动作有三个-print 默认选项,显示名称,-o -print 表示不仅仅显示目录名,还显示目录里面的文件名 -ls 显示文件属性 -exec 命令 {} \; 使用命令对查找结果处理,查找结果使用"{}"来表示
# 通过文件名查询 查询当前路径下demo.py文件
find ./ -name demo.py
# 查找符号链接文件
find ./ -type l -print
# 查找类型文件
find ./ -type f -print
# 按时间查找
# 查找2天内被更改过的文件
$ find . -mtime -2 -type f -print
# 查找2天前被更改过的文件
$ find . -mtime +2 -type f -print
# 查找一天内被访问的文件
$ find . -atime -1 -type f -print
# 查找磁盘中 大于30k的文件
$ find . -size +30k -exec ls -ld {} \;
# 删除old后缀的文件 查找的结果使用 {} 表示
$ find ./ -name '*.old' -exec rm -rf {} \;