文章目录
一、基础知识
核心命令
筛选命令相关:
快捷键:
!!
执行上一条命令!num
num为历史命令编号,可以输入history查看历史命令Ctrl + r
根据输入的关键字查找历史命令
命令行切换:
Ctrl + A
光标迅速回到行首Ctrl + E
光标迅速回到行尾Esc + b
移动到当前单词的开头Esc + f
移动到当前单词的结尾Ctrl + k
删除光标到行尾的内容Ctrl + u
删除光标到行首的内容Ctrl + y
粘贴删除的内容Ctrl + c
临时停止命令行命令
grep
查询文件中的内容- 格式:
grep 参数 查询的内容 文件名
- 参数:
-i
不区分大小写-n
显示行号-v
对查询的内容取反-w
按单词查询-o
打印匹配关键字-c
统计匹配的次数-r
逐层遍历目录查询-Anum
查询多少行的后几行-Bnum
查询多少行的前几行-Cnum
查询多少行的前后几行-l
只列出匹配的文件名-L
列出不匹配的文件名-e
使用正则匹配^关键字
返回行首以关键字开头的文件路径关键字$
以关键字结尾^$
匹配空行--color=auto
可以给查询到的内容添加颜色
- 格式:
sort
对文件内容排序- 格式:
sort 参数 文件名
-u
去重-r
降序,默认为升序-o
对排序后的文件重新写入另一个文件-n
以数字进行升序,默认是按字符排序-t
分隔符-b
忽略前导空格-R
随机排序
- 格式:
信息处理命令相关:
cut
数据截取- 格式:
cut 参数 文件名
-b
只截取指定的字节-c
只截取指定的字符-d
按分隔符进行截取-f
截取每行中的第几列,要想获取多列需要用逗号隔开cut -d: -f1 a.txt
以:
进行切割并获取第一列的数据
- 格式:
tr
数据缩减、替换、删除-c
根据指定的关键字符进行替换字符前后的数据tr -c ":" "@" < a.txt
会将:
前后替换为@
-s
根据指定的关键字符进行缩减tr -s " " < a.txt
将行首的多个空格缩减为一个空格
-d
根据指定的关键字进行删除tr -d ":" < a.txt
删除文件中包含:
符号
tr "root" "ROOT" < a.txt
将小写的root替换成大写的ROOT
uniq
连续去重-c
计数去重的个数uniq -c a.txt
-i
不区分大小写-d
只显示去重的内容-n
显示行号
组合信息相关命令:
paste
合并文件行输出到屏幕,但不会改变数据源-d
指定每列之间的分隔符paste -d'@' a.txt
-s
将多行转为一行输出
xargs
命令结果传递作用:可以将管道符或标准输入数据转换成命令行参数,也能够从文件的输出中读取数据
格式:命令 | xargs 参数 命令
-a
从文件中读取数据作为标准输入[root@VM-12-9-centos num]# xargs -a a.txt aaa bbb
-E
读取数据时以分隔符进行分隔[root@VM-12-9-centos num]# xargs -a a.txt -n 2 -p -E " " echo aaa bbb ?...y aaa bbb
-p
每次读取数据时询问用户[root@VM-12-9-centos num]# xargs -a a.txt -n 1 -p echo aaa ?...y aaa
-n num
执行命令时一次所使用的个数,默认是所有的[root@VM-12-9-centos num]# xargs -a a.txt -n 1 aaa bbb
-t
先打印命令然后再执行-I
将接受的数据逐行赋值给{}
,相当于将结果临时存储在{}
中,也可以当变量使用[root@VM-12-9-centos num]# xargs -a a.txt -I {} echo {}-结果 aaa-结果 bbb-结果
[root@VM-12-9-centos num]# ls *.txt | xargs -I {} cp {} /usr/local/{} 查看所有以txt结尾的文件,并将它们复制到/usr/local/原文件 下
-r
当输入为空时停止执行该命令-d
分隔符,默认的分隔符是空格,可以通过该参数指定分隔符[root@VM-12-9-centos num]# echo "xnamexnamexnamexname" | xargs -d "x" name name name name
shell基础
脚本的执行方法:
1️⃣ 强烈推荐:
[root@VM-12-9-centos shell]# /bin/bash /usr/local/getNetWorkDataInfo.sh IP: 172.17.0.1 Netmask: 255.255.0.0 Broadcast: 172.17.255.255 MAC Address: 02:42:89:d8:ad:30
2️⃣ 执行需要权限
[root@VM-12-9-centos shell]# ./getNetWorkDataInfo.sh -bash: ./getNetWorkDataInfo.sh: 权限不够
3️⃣ 不推荐
[root@VM-12-9-centos shell]# . getNetWorkDataInfo.sh IP: 172.17.0.1 Netmask: 255.255.0.0 Broadcast: 172.17.255.255 MAC Address: 02:42:89:d8:ad:30 当然 . 还可以换成 source
4️⃣ 1的变种版:
[root@VM-12-9-centos shell]# cat getNetWorkDataInfo.sh | bash IP: 172.17.0.1 Netmask: 255.255.0.0 Broadcast: 172.17.255.255 MAC Address: 02:42:89:d8:ad:30
脚本的调试:
-n
检查脚本中的语法错误[root@VM-12-9-centos shell]# /bin/bash -n getNetWorkDataInfoError.sh getNetWorkDataInfoError.sh:行8: 寻找匹配的 `"' 是遇到了未预期的文件结束符 getNetWorkDataInfoError.sh:行9: 语法错误: 未预期的文件结尾
-v
逐行执行并显示结果,遇到错误显示错误。适用小型脚本[root@VM-12-9-centos shell]# /bin/bash -v getNetWorkDataInfoError.sh #!/bin/bash :<<! 获取ip地址、掩码地址、广播地址、MAC地址 ! ifconfig docker0 | grep -w inet | tr -s " " | cut -d " " -f 3 | xargs -I {} echo "IP: " {} IP: 172.17.0.1 ifconfig docker0 | grep -w inet | tr -s " " | cut -d " " -f 5 | xargs -I {} echo "Netmask: " {} Netmask: 255.255.0.0 ifconfig docker0 | grep -w inet | tr -s " " | cut -d " " -f 7 | xargs -I {} echo "Broadcast: " {} Broadcast: 172.17.255.255 ifconfig docker0 | grep -w ether | tr -s " " | cut -d " " -f 3 | xargs -I {} echo "MAC Address: {} getNetWorkDataInfoError.sh:行8: 寻找匹配的 `"' 是遇到了未预期的文件结束符 getNetWorkDataInfoError.sh:行9: 语法错误: 未预期的文件结尾
-x
将执行的每条命令和执行结果都打印出来,适用复杂脚本[root@VM-12-9-centos shell]# /bin/bash -x getNetWorkDataInfoError.sh + : + ifconfig docker0 + grep -w inet + tr -s ' ' + cut -d ' ' -f 3 + xargs -I '{}' echo 'IP: ' '{}' IP: 172.17.0.1 + ifconfig docker0 + cut -d ' ' -f 5 + tr -s ' ' + xargs -I '{}' echo 'Netmask: ' '{}' + grep -w inet Netmask: 255.255.0.0 + ifconfig docker0 + xargs -I '{}' echo 'Broadcast: ' '{}' + grep -w inet + tr -s ' ' + cut -d ' ' -f 7 Broadcast: 172.17.255.255 getNetWorkDataInfoError.sh:行8: 寻找匹配的 `"' 是遇到了未预期的文件结束符 getNetWorkDataInfoError.sh:行9: 语法错误: 未预期的文件结尾
shell变量
基本格式:
$变量名 | "$变量名" | ${变量名} | "${变量名}"
基础变量
变量定义:
- 变量包括:变量名 、变量值、赋值动作。
- 格式:
变量名=变量值
=
两边不允许有空格,因为空格代表两个命令的隔开
类型变量定义:
- 格式:
declare 参数 变量名=变量值
- 参数:
-i
定义为整数,类型不一致会出错-r
该变量只能读-x
定义为全局变量-a
定义普通数组-A
定义为关联数组
- 格式:
变量的移除:
- 格式:
unset 变量名
- 格式:
本地变量
变量名仅仅在当前终端使用
变量分类:
普通变量:
变量名=变量值
格式:
变量名=变量值
变量值必须是一个整个变量名='变量值'
原样输出变量名="变量值"
如果变量值中存在其它变量可以先进行解析然后赋值给新的变量名
命令变量:通过命令将结果赋值给变量名
变量名=命令
格式:
1.变量名=`命令` [root@VM-12-9-centos shell]# name=`/bin/bash getNetWorkDataInfo.sh` [root@VM-12-9-centos shell]# echo $name IP: 172.17.0.1 Netmask: 255.255.0.0 Broadcast: 172.17.255.255 MAC Address: 02:42:89:d8:ad:30 2.变量名=$(命令) [root@VM-12-9-centos shell]# name=$(/bin/bash getNetWorkDataInfo.sh) [root@VM-12-9-centos shell]# echo $name IP: 172.17.0.1 Netmask: 255.255.0.0 Broadcast: 172.17.255.255 MAC Address: 02:42:89:d8:ad:30
全局变量
变量名能够在当前操作系统中的所有终端使用
- 查看全局变量:
env
printenv
export
declare -x
- 查看全局变量:
变量文件:创建在用户范围的只能自己查看,创建在系统范围的可以在多个用户查看
用户范围:
./bashrc ./bash_profile
系统范围:
/etc/profile /etc/profile.d/env_file_name
内置变量
脚本相关内置变量
变量名 解释 $0 获得当前执行shell脚本的名称 $n 获得当前执行脚本的第n个参数,如果n大于10用大括号包裹起来${10} $# 获得当前shell命令行中参数的总个数 $? 获得上一条命令执行的返回值(0为成功,非0代表失败) 字符串相关内置变量
length: ${#字符串} 获取字符串的长度 [root@VM-12-9-centos shell]# name="zhangsan" [root@VM-12-9-centos shell]# echo ${#name} 8
split: ${字符串:索引起始位置:截取的个数} [root@VM-12-9-centos shell]# echo ${name:0:5} zhang
默认值内置相关变量
格式一:${变量值:-默认值} 如果变量值有值,则输出变量值,如果没有则输出默认值 [root@VM-12-9-centos shell]# echo ${name:-lisi} zhangsan
格式二:${变量值:+默认值} 无论变量值是否有值都输出默认值 [root@VM-12-9-centos shell]# echo ${name:+lisi} lisi
其它内置相关变量
变量名 解释 $_ 在次之前执行命令或脚本的第一个内容:/bin/bash text.sh arg1 ,即这里的/bin/bash $@ 获取所有传递的参数 $* 以单字符串显示向脚本里传递的参数 $$ 显示当前执行脚本的进程ID $! 显示上一条命令进程的ID [root@VM-12-9-centos shell]# /bin/bash getNetWorkDataInfo.sh docker0 ent1 ent2 IP: 172.17.0.1 Netmask: 255.255.0.0 Broadcast: 172.17.255.255 MAC Address: 02:42:89:d8:ad:30 docker0 ent1 ent2 docker0 ent1 ent2 13487
内容格式化
常用符号解读
重定向
> 将符号左边的内容覆盖传递给符号右边的内容 < 将符号右边的内容覆盖传递给符号左边的内容 >> 将符号左边的内容追加传递给符号右边的内容 << 将符号右边的内容追加传递给符号左边的内容
管道符
| 将左侧的内容传递给右侧
后台执行
命令 & 前台执行的命令放到后台执行
信息符号
1 正确输出 示例:echo "zhangsan" 1> stand1.txt & 2 错误输出 示例:echo1 "zhangsan" 2> standerror.txt & 2>&1 全部输出 示例:echo "zhangsan" | echo1 123 > standout.txt 2>&1 &
输入格式化
EOF
将文件内容按原格式输入到另外一个文件#!/bin/bash cat > file.txt << EOF 你好: 您吃了吗? -- 2022/02/22 EOF
需要注意的是:结尾的EOF需要顶格
tee
跟 重定向具有相同功能,同时还支持标准输出到多个文件[root@VM-12-9-centos shell]# cat <<EOF | sudo tee /usr/local/shell/a.txt > > 标准输出: > EOF 标准输出:
输出格式化
echo
将内容输出到指定位置,默认输出到控制台并且行尾会自动带有换行符-n
取消自动换行-e
当出现以下字符进行特别处理:
字符 | 释义 |
---|---|
\a | 发出警告声 |
\b | 删除前一个字符 |
\c | 行尾不加换行符 |
\f | 换行但光标任停在原来的位置 |
\n | 换行且光标停在行首的位置 |
\r | 光标移至行首,但不换行 |
\t | 插入tab |
\v | 同\f一致 |
\ | 插入\字符 |
\0nnn | 打印nnn(八进制)所代表的ASCII字符 |
\xNN | 打印十六进制所代表的ASCII字符 |
- echo 自定义颜色
- 格式:
echo -e "\033[41;31m 内容 \033[0m"
第一个\033可以用\e代替,[是固定的,4开头代表背景色,3开头代表文字的颜色
色彩 黑 红 绿 黄 蓝 紫 青 灰
字体色 30 31 32 33 34 35 36 37
背景色 40 41 42 43 44 45 46 47
结束控制符:
\033[0m 关闭所有属性 \033[1m 设置高亮度 \033[4m 下划线 \033[5m 闪烁 \033[7m 反显 \033[8m消隐
printf
输出,并且可以使用格式化替换符,但不会自动换行
printf
"姓名:%s
身高:%f
" " 张三 " 180
格式化替换符:
%s | 替换字符串 |
---|---|
%d,%i | 十进制整数 |
%f | 浮点数 |
%c | ASCII字符,即显示对应参数的第一个字符 |
%b | 相对应的参数中包含转义字符时,可以使用%b进行替换,对应的转义字符可以转义 |
%o | 八进制符 |
%u | 不带正负号的十进制值 |
%x | 十六进制值(a-f) |
%X | 十六进制(A-F) |
%% | %自己本身 |
格式化转义字符:
\n | 换行 |
---|---|
\r | 回车 |
\t | 水平制表符 |
\\ | 一个反斜杠字符 |
脚本交互
基础知识
- 配置文件:
- 系统级别:
/etc/profile
为系统的每个用户设置环境信息,当用户第一次登录时会执行该文件/etc/profile.d/*.sh
被/etc/profile
文件调用,执行当前文件中的所有*.sh
文件的设置/etc/bashrc
为每一个运行bash shell
的用户执行此文件
- 用户级别:
~/.bash_profile
设定用户专用的shell
信息,当用户登录时该文件只执行一次。~/.bashrc
该文件包含用户专用的bash
信息,当用户登录或每次打开shell
文件时会执行。
- 配置文件:
su
命令su -
切换指定用户的身份包括该用户的所有工作环境su -l
同- 类似,需要在指定切换的用户账号su -p
切换指定用户的身份,但不改变工作环境su -m
同-p
一样su -c
仅切换一次,切换后执行一条命令会自动切换回去
修改配置文生效的两种方式:
- 关闭窗口重新打开
source
文件路劲
临时
shell
- 启动子
shell
,可以通过(执行操作外部不会受影响) - 不启动子
shell
,{执行操作会对外部造成影响}
- 启动子
shell表达式
运算符表达式
- 赋值运算:
=
*=
/=
%=``+-
-=
<<=
>>=
&=
^=
|=
- 二元运算:
+
-
*
/
%
- 高阶运算:
**
^
++
--
- 其它运算:
<<
>>
- 赋值运算:
计算表达式
- 将多个值进行计算:
$[]
let
(())
$(())
expr
bc
$[ 20 + 5 ]
常用于整数的计算,不太适合负责的场景,运算结果是小数会自动取整let 变量a=变量a+5
注意:表达式必须是一个整体,等号两边不允许有空格((变量计算表达式))
如:(( a += 5 ))
,表达式可以不是一个整体$((变量表达式))
可以组合使用echo $((a += 5))
expr
可用作数字计算也可以用作字符串进行计算- 用作数字计算:
expr $((1+1))
- 用作字符串:
expr match 字符串 匹配内容
最终返回的是匹配内容的长度
expr substr 字符串 起始索引 截取长度
注意:起始位置需要>=1
expr index 字符串 字符
返回字符出现在字符串中的第一个位置,从1开始
expr length 字符串
返回字符串的长度
- 用作数字计算:
bc
是一种任意精度的计算语言,提供了语法结构,如条件判断,循环等。还可以进行进制转换- 常见参数:
-i
强制交互模式
-l
使用bc的内置库,比如一些数学库对三角计算非常有用
-q
纯净交互模式 - 特殊变量:
ibase
,obase
用于进制转换,ibase
是输入的进制,obase
是输出的进制,默认是十进制。scale
保留小数位,默认是0位。
bc
主要用途是来获取小数点的后几位,也就使用scale
- 常见参数:
[root@VM-12-9-centos ~]# echo " 4 * 5 " | bc 20 [root@VM-12-9-centos ~]#
[root@VM-12-9-centos ~]# echo "scale=1; 10.23222 / 3.123 " | bc 3.2 [root@VM-12-9-centos ~]# 乘以似乎不太好用
- 将多个值进行计算:
测试表达式
- 对结果进行判断:
test []
[[]]
- 格式:
test 表达式
通过$?
对变量进行判断 满足返回0 不满足返回非0 - 格式:
[ 表达式 ]
这种表达式比较严谨,推荐使用,同样 通过$?
对变量进行判断 满足条件返回0不满足返回非0 - 格式:
[[ 源内容 匹配符 匹配内容 ]]
,但中括号的增强版,可以匹配通配符和正则表达式,其中==
匹配符会精确匹配内容,=~
源内容会模糊匹配 匹配内容。[[ zhang == zha.* ]]
使用
test -v empty
对空值进行判断- 对结果进行判断:
逻辑表达式
- 多场景的组合使用:
&&
||
and
or
not
&
|
- 多场景的组合使用:
比较表达式
- 判断数据之间的适配关系:
-f|d|s
-r|x|w
-e
-n
==
!=
>
<
<=
>=
- 判断数据之间的适配关系:
字符串的判断:
-z str
空值判断,长度为0返回true,否则返回false-n "str"
非空判断,长度不为0返回true,否则返回false
文件的判断:
-d
判断文件是否存在且为目录文件-f
判断文件是否存在且为普通文件-S
判断文件是否存在且为socket 文件-L
判断文件是否存在且为链接文件-O
判断文件是否存在且为当前用户所有-G
判断文件是否存在且默认组是否为当前用户组
文件权限的判断:
-r
判断文件是否可读-w
判断文件是否可写-x
判断文件是否可执行
文件存在的判断:
-e
判断文件是否存在-s
判断文件是否存在且不为空
文件新旧判断:
file1 -nt file2
判断文件1是否比文件2新file1 -ot file2
判断文件1是否比文件2旧file1 -ef file2
判断文件是否为同一文件,根据节点i
来判断
数字的判断:
-eq
相等-ne
不相等-ge
大于等于-gt
大于-lt
小于-le
小于等于
三元表达式
- 多逻辑的计算表达式:
expr ? expr : expr
- 多逻辑的计算表达式:
集合表达式
- 表达式之间的关联关系:
[[]]
[ -a|o ]
[ ! ]
- 在集合中,1代表为true,0代表false,与之前的表达式刚好是相反的
$[ 1 | 1 ]
返回1,$[ 1 & 0 ]
返回0- 逻辑组合:多个逻辑的综合结果
[ 1 == 1 -a 1 != 1 ]
两个条件满足后整体返回true[ 1 == 1 -o 1 != 1 ]
两个条件任一一个满足返回true[[ 1 == 1 && 1 != 1 ]]
两个条件同时满足返回true[[ 1 == 1 || 1 != 1 ]]
任意一个条件满足即返回true
- 表达式之间的关联关系:
数组操作
- 数组定义:在
shell
中只支持一维数组,每个元素之间通过空格隔开,当然也可以使用命令定义。[root@VM-12-9-centos ~]# arr=(11 22 33 44 ) [root@VM-12-9-centos ~]# echo ${arr[3]} 44 [root@VM-12-9-centos ~]# echo ${arr[@]} 11 22 33 44 [root@VM-12-9-centos ~]#
- 数组的获取:
${arr[index]}
获取指定位置的索引,${arr[@]: 起始位置: 获取数量}
或者${arr[*]: 起始位置: 获取数量}
[root@VM-12-9-centos ~]# echo ${arr[@]: 0 : 2} 11 22 [root@VM-12-9-centos ~]# echo ${arr[*]: 1 : 3} 22 33 44 [root@VM-12-9-centos ~]#
- 数组的修改:
[root@VM-12-9-centos ~]# arr[0]=12 [root@VM-12-9-centos ~]# echo ${arr[0]} 12 [root@VM-12-9-centos ~]#
- 数组的删除:
[root@VM-12-9-centos ~]# unset arr [root@VM-12-9-centos ~]# echo ${arr[@]} [root@VM-12-9-centos ~]#
- 关联数组:
- 定义关联数组:
declare -A arr_name
,关联数组必须先声明再使用,即将下标变成字母[root@VM-12-9-centos ~]# source=(["星期一"]="上班" ["星期二"]="上班" ["星期三"]="上班") [root@VM-12-9-centos ~]# echo ${source[@]} 上班 上班 上班 [root@VM-12-9-centos ~]# echo ${source[星期一]} 上班 [root@VM-12-9-centos ~]# declare -A | grep source declare -A source='([星期三]="上班" [星期一]="上班" [星期二]="上班" )' [root@VM-12-9-centos ~]#
二、流程控制
条件控制
if
控制语句- 单分支
- 格式:
if [ 条件 ]
then
指令
fi
其中条件还可以是 :
[[ 条件 ]]
(( 命令 ))
- 双分支
- 格式:
if [ 条件 ]
then
指令1
else
指令2
fi
- 多分支
- 格式:
if [ 条件1 ]
then
指令1
elif [ 条件2 ]
then
指令2
else
指令3
fi
- 单行命令写法:条件一个分号,then指令一个分号;
if [ 条件 ]; then 指令; elif [ 条件 ]; then 指令; else 指令; fi
case
控制语句- 多用于多分支判断
- 格式:
case 变量名或表达式 in
值1)
指令1;;
值2)
指令2;;
*)
指令3;;
esac
注意点:
*
不能使用双引号,并且不能放在首位
循环控制
for
控制语句- 语法结构:
for 值 in 列表
do
执行语句
done
- 双小括号语法结构:
for (( i=0; i<10; i++ ))
do
执行语句
done
for (( i=0; i<10; i++ ));do 执行语句;done
for (( i=0,j=0; i<10; i++,j++ )); do 执行语句; done
for (( i=0,j=0; i<10; i++,j++ ))
do
执行语句
done
注意点:
1.变量的赋值可以包含空格
2.条件中的变量不能用$
符号
3.第三部分的数据操作过程不能用expr
格式
while
控制语句until
控制语句select
控制语句
过程控制
continue
控制语句break
控制语句exit
控制语句shift
控制语句