距离上次开新的文章已经过了四个月了.......真快
上次编辑4.14..........现在5.29............
shell基础
主要内部使用,基本不考虑效率
简化工作流程
练习: 先照着敲,然后看着代码写注释, 删掉代码看着注释写代码
shell : 命令解释器
Linux shell : BASH shell
unix shell : C Shell
控制字符
控制字符 |
作 用 |
\\ |
输出\ 本身 |
\a |
输出警告音 |
\b |
退格键,也就是向左删除 |
\c |
取消输出行末的换行符,和 -n 选项一致 |
\e |
Escape键 |
\f |
换页符 |
\n |
换行符 |
\r |
回车键 |
\t |
制表符 也就是Tab键 |
\v |
垂直制表符 ?? |
\0nnn |
按照八进制ASCII码表输出字符,其中0为数字0,nnn是三位八进制数 |
\xhh |
按照十六进制ASCII码表输出字符,其中hh是两位十六进制数 |
echo命令
1.echo 命令
echo [选项] ["输出内容"]
-e : 支持反斜线控制的字符转换 具体看上方控制字符表
-n : 取消输出后行末的换行符号
注意: 如果输出内容里面有空格需要加""
echo -e \e[1;31m test \e[0m 解释:
\e[1; : 执行颜色输出开始
31m : 颜色 30m 黑色; 31m红色; 32m绿色; 33m黄色;34m蓝色;35m洋红;36m青色;37m白色; \
40开始是背景颜色
\e[0m :结束颜色输出
shell脚本的执行
#!/bin/bash
echo "hello word"
两种执行方法:
赋予执行权限,直接运行,绝对路径/root/sh/hello.sh 相对路径./hello.sh
通过bash调用执行脚本 bash hello.sh 甚至不需要赋予执行权限
Bash的基本功能
history [选项] //查询历史命令
-c : 清空历史命令,平常的历史命令有助于排错,但是配置mysql会在命令输入密码,所以清空
-w : 把缓存中的历史命令写入历史命令保存文件,如果不手工指定历史命令保存文件,则放入默认历史命令保存文件~/.bash_history中
/etc/profile可以设置历史命令最多存多少 HISTSIZE=1000 默认1000,可以调大,暂存在硬盘
调用历史命令
键盘上下箭头调整
!n : n是history命令中的标号,适用于隔了好几个命令的输入
!! : 重复上一条命令
!字符串 : 重复最后一个开头字符串的命令 如 vim
!$ : 重复上一条命令的最后一个参数
补全,命令与文件的补全
快捷键
快捷键 |
作 用 |
ctrl+A |
把光标移动到命令行开头,如果输入过长,想移动到开头使用 |
ctrl+E |
把光标移动到命令行结尾 |
ctrl+C |
强制终止当前命令 |
ctrl+L |
清屏相当于clear命令 |
ctrl+U |
删除或剪切光标之前的命令 |
ctrl+K |
删除或剪切光标之后的命令 |
ctrl+Y |
粘贴ctrl+U或ctrl+K剪切的内容 |
ctrl+R |
在历史命令中搜索,按下ctrl+R之后,就会出现搜索界面,只要输入搜索内容,就会从历史命令搜索 |
ctrl+D |
退出当前终端 |
ctrl+Z |
暂停,并放入后台,这个快捷键牵扯工作管理的内容,在系统管理详细介绍 |
ctrl+S |
暂停屏幕输出 |
ctrl+Q |
恢复屏幕输出 |
输入输出重定向
1.bash的标准输入输出
设备 |
设备文件名 |
文件描述符 |
类型 |
键盘 |
/dev/stdin |
0 |
标准输入 |
显示器 |
/dev/stdout |
1 |
标准输出 |
显示器 |
/dev/stderr |
2 |
标准错误输出 |
2.输出重定向 常见
类型 |
符号 |
作用 |
标准输出重定向 |
命令 >文件 |
以覆盖的方式,把命令的正确输出输出到指定的文件或设备中 |
|
命令 >>文件 |
以追加的方式,把命令的正确输出输出到指定的文件或设备中 |
标准错误输出重定向 |
错误命令 2>文件 |
以覆盖的方式,把命令的错误输出输出到指定的文件或设备中 |
|
错误命令 2>>文件 |
以追加的方式,把命令的错误输出输出到指定的文件或设备中 |
正确错误输出all save |
命令 > 文件 2>&1 |
以覆盖的方式,把正确输出和错误的输出都保存到同一个文件中 |
|
*命令 >>文件 2>&1 |
以追加的方式,把正确输出和错误的输出都保存到同一个文件中 |
|
命令 &> 文件 |
以覆盖的方式,把正确输出和错误的输出都保存到同一个文件中 |
|
*命令 &>> 文件 |
以追加的方式,把正确输出和错误的输出都保存到同一个文件中 |
|
*命令 >> 文件1 2 >>文件2 |
把正确的输出追加到文件1中,把错误的输出追加到文件2中 |
*为常用
3.输入重定向 不常见
wc < 1.txt // 统计 1.txt的字节 单词数 和行数, 正常就是不加< 只有打补丁或者及其偶尔用得到
wc << zyx
>aslkdjflksadjf
>aslkdfjlsakdjflasdf
>aslkdjflkasdjflsak
>zyx
// zyx为停止符,统计这一段有多少字节, 单词数 行数, <<没啥用
多命令顺序执行
多命令执行符 |
格式 |
作 用 |
; |
命令1 ; 命令2... |
多个命令顺序执行,命令之间没有任何逻辑联系,就算前面出错后面也会继续执行 |
&& |
命令1 && 命令2... |
当命令1正确执行(($?=0) 则命令2才会执行; 当命令1执行不正确($?≠0) 则命令2不会执行 |
|| |
命令1 || 命令2 ... |
当命令1 执行不正确 ($?≠0),则命令2才会执行; 当命令1正确执行($?=0),则命令2不会执行 |
ls && echo yes || echo no
单分支判断语句
bash中的特殊符号
符号 |
作用 |
'' |
单引号,在单引号中的所有特殊符号,如'$'和' ` '(反引号)都没有特殊含义 |
"" |
双引号,在双引号中特殊字符都没有特殊含义,但是"$"调用变量的值, "`"引用命令, 和"\"转义符例外 |
`` |
反引号,反引号括起来的内容是系统命令,在bash中会先执行它,和$()作用一样,不过推荐使用$(),因为反引号容易看错 |
$() |
和反引号作用一样,用来引用系统命令 |
() |
用于一串命令执行时,()中的命令会在 子shell 中运行 局部变量, 临时变量 |
{} |
用于一串命令执行时,{}中的命令会在当前shell中执行,也可用于变量变形与替换 |
[] |
用于变量的测试 后面会讲 |
# |
注释,在shell脚本中,#开头的行代表注释 |
$ |
调用变量的值,如需要调用变量name的值时,需要用$name的方式得到变量的值 |
\ |
转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符,如果\$将输出$符号,而不是当作变量引用 |
()和{}的区别: 不常用
-()执行一串命令时,需要重新开一个子shell进行执行
-{}执行一串命令时,是在当前shell执行
-(){}都是把一串命令放在括号里,并且命令之间用;号隔开
-()最后一个命令可以不用;号
-{}最后一个命令要用;号
-{}的第一个命令和左括号之间必须要有一个空格
-()里的命令不需要和括号有空格
-(){}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令
变量
变量的定义
-变量名称可以由字母、数字和下划线组成,但是不能以数字开头。如果变量名是“2name” 则是错误的。
-在Bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必修指定变量类型为 数值型。
-变量用等号连接值,等号左右两侧不能有空格。
-变量的值如果有空格,需要使用单引号或双引号包括。如:“test=" hello world!"”。其 中双引号括起来的内容“$”、“\”和反引号都拥有特殊含义,而单引号括起来的内容都是 普通字符。
-在变量的值中,可以使用“\”转义符。
-如果需要增加变量的值,那么可以进行变量值的叠加。不过变量需要用双引号包含"$变量名 或用${变量名}包含变量名
-定义变量不需要加$,使用变量时需要加$
例如:
test=123
test="$test"456 // 用这个
echo $test
123456
test=${test}789 // 别扭
echo $test789
123456789
如果把命令的结果作为变量赋值变量,则需要使用反引号或 $()包括命令:
test=$(date)
echo $test
2021年4月12日13点59分
变量的分类
- 用户自定义变量这种变量是最常见的变量,由用户自由定义变量名和变量的值
- 环境变量:这种变量中主要保存的是和系统操作环境相关的数据,比如当前登录用户,用户的家目录,命令的提示符等。不是太好理解吧,那么大家还记得在 Windows中,同一台电脑可以有多个用户登录,而且每个用户都可以定义自己的桌面样式和分辨率,这些其实就是Windows的操作环境,可以当做是 Windows的环境变量来理解。环境变量的变量名可以自由定义,但是一般对系统起作用的环境变量的变量名是系统预先设定好的。
- 位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
- 预定义变量:是Bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
变量分类 |
名称 |
作用 |
内容 |
用户自定义变量 |
自定义 |
自定义 只能在本shell生效 |
自定义 |
用户自定义环境变量 大写 |
自定义 |
自定义 可以在子shell生效 |
自定义 |
系统自带环境变量 大写 |
确定 |
确定 |
自定义 |
*位置参数变量 |
确定 |
确定 |
自定义 |
*预定义变量 |
确定 |
确定 |
自定义 |
用户自定义变量
查看
set [选项]
-u : 调用未声明变量时会报错
-x : 在命令执行之前,会把命令先输出一次 不建议
// 什么都不加那就查看系统所有变量
env 也能查看环境变量
删除
unset 变量名 // 删除变量
环境变量
用户自定义环境变量:
export AGE="22"
用export声明的变量即时环境变量 删除也是unset
实际使用了declare -x 这相当于简化版
系统环境变量:
-- PATH环境变量: 系统查找命令的路径
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
// PATH变量的值是用':'分割路径,这些路径就是系统查找命令的路径,也就是说但我们输入了一个程序名,如果没有写入路径,下体哦那个就会到PATH变量定义的路径中去寻找,是否有可以只能怪的程序,如果找到则执行,否则会报'命令没有发现'的错误
临时生效
// 把脚本拷贝到PATH变量等一的路径中,我们自己写的脚本也可以不输入路径直接运行
cp test.sh /usr/bin
// 也可以修改PATH变量的值,而不是把程序脚本复制到PATH的路径中,使用叠加变量
PATH="$PATH": 你想放的绝对路径
永久生效:
待补充
-- PS1环境变量: 命令提示符设置
PS1='[\u@\h \W]\$] '
\d:显示日期,格式为“星期月日”
\H:显示完整的主机名。如默认主机名“1 Localhost.1 ocaldomain”
\h:显示简写主机名。如默认主机名“1 localhost
\t:显示24小时制时间,格式为“HH:MM:SS”
\T:显示12小时制时间,格式为“HH:MM:SS”
\A:显示24小时制时间,格式为“HH:MM”
\@:显示12小时制时间,格式为“HH:MMam/pm
\u:显示当前用户名
\v:显示Bash的版本信息
\w:显示当前所在目录的完整名称
\W:显示当前所在目录的最后一个目录
\#:执行的第几个命令
\$:提示符。如果是root用户会显示提示符为“#”,如果是普通用户会显示提示符为$
永久生效:
/etc/profile.d/env.sh文件下
-- LANG 语系变量
echo $LANG // 查询当前语言
locale // 查询语系 -a 看全部
/etc/sysconfig/i18n 文件下修改
LANG="zh_CN.UTF-8" 来定义系统默认语言
linux 中文支持
安装了中文字体和编码
操作终端必须支持中文编码
位置参数变量
位置参数变量 |
作 用 |
$n |
n为数字,$0代表命令本身,$1-$9代表第1-9个参数,10以上的参数需要用大{},如${10} |
$* |
代表命令行中所有的参数,$*把所有的参数看成一个整体 |
$@ |
也代表命令行中所有的参数,不过$@把每个参数区分对待 |
$# |
这个变量代表命令行中所有从参数的个数 |
#!/bin/bash // 脚本必加
a=$1 // 脚本后的第一个参数
b=$2 // 脚本后的第二个参数
sum=$(($a + $b )) // $双小于号 进行数字运算
echo $sum // 输出 sum
------------------------------------------------------------------
chmod 755 count.sh
./count.sh 11 22
33
------------------------------------------------------------------
只给作者用没有提示,之后学read就会有提示了
#!/bin/bash
echo "\$* is $*"
echo "\$@ is $@"
echo "\$# is $*"
--------------------------------
./para.sh 11 22 33 44
$* is 11 22 33 44 // 乍看这俩一样
$@ is 11 22 33 44 // 乍看这俩一样
$# is 4 // 统计个数
=================================
#!/bin/bash
for i in "$*" // 循环, 因为$*把参数看作一个整体,所以执行一次就结束了
// shell语言的for in 后面有几个数就循环几次
do
echo $i
done
for y in "$@" // 循环, 因为$@把参数当成个体,所以会执行多次(当参数有多个时)
do // 类似于 {
echo $y
done // 类似于 }
--------------------------------
./para2.sh 11 22 33 44
11 22 33 44
11
22
33
44
预定义变量
预定义变量 |
作用 |
$? |
最后一次执行的命令的返回状态,如果这个变量的值为0,证明上一个命令正确执行,如果非0,则上一个命令不正确 |
$$ |
当前进程的进程号 PID |
$! |
后台运行的最后一个进程的进程号 |
接受键盘输入read
read [选项] [变量名] // 适合让用户进行输入
-p "提示信息" : 在等待read输入时,输出提示信息
-t 秒数 : read命令会一直等待用户输入,使用此选项可以指定等待时间
-n 字符数 : read命令只接受指定的字符数,就会执行
-s : 隐藏输入的数据,适用于机密信息输入
变量名:
变量名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY
如果只提供了一个变量名,则整个输入行赋予该变量
如果提供了一个以上的变量名,则输入行分为若干字,一个接一个的赋予各个变量,而命令行上
$!/bin/bash
read -p "请你输入数字1:" num1
read -p "请你输入数字2:" num2
sum=$(($sum1+sum2))
echo "和为:$sum"
--------------------------------------------
./count2
请你输入数字1:11
请你输入数字2:22
和为:33
运算
声明变量declare
既然所有变量的默认类型是字符串型,那么只要我们把变量声明为整数型不就可以运算了嘛,使用declare命令就可以时限声明变量的类型
declare [+/-] [选项] 变量名
- - : 给变量设定类型属性
- + : 取消变量的类型属性
- -a : 将变量声明为数组型
- -i : 将变量声明为整数型(integer)
- -r : 将变量声明为只读变量,注意,一旦设置为只读属性,既不能修改变量的值,也不能删除变量,甚至不能通过+r取消只读属性
- -x : 将变量声明为环境变量 就是export命令复杂版
- -p : 显式指定变量的被声明的类型 直接-p查所有
定义数组
declare -a name[0]="sc" // 变量后面加[]就相当于直接创建数组
name[1]="lm" // 直接调用就可以
调用:
echo ${name} // 调用第一个 [0]
echo ${name[*]} // 调用全部,把*换成数字就是调用数组里面第几个-1
只读变量
declare -r test
如果这个变量是在命令行声明的,重启才能消失,如果确实写入了环境变量配置文件,那就不可修改
数值运算
常用方法:
$((运算式)) 或 $[运算式] // 由于[]还有其他作用,最常用的还是$((运算式))
其他方法1:
a=11
b=22
declare -i c=$a+$b
echo $c
---------------------------------
33
其他方法2:
d=$(expr $a + $b) // 很麻烦, + 两边必须加空格
echo $d
---------------------------------
33
其他方法3:
let e=$a+$b
echo $e
---------------------------------
33
运算符与优先级
优先级 |
运算符 |
说明 |
13 |
-,+ |
单目负,单目正 |
12 |
!,~ |
逻辑非,按位取反或补码· |
11 |
*,/,% |
乘,除,取模 |
10 |
+,- |
加,减 |
9 |
<<,>> |
按位左移,按位右移 |
8 |
<=,>=,<,> |
小于等于,大于等于,小于,大于 |
7 |
==,!= |
等于,不等于 |
6 |
& |
按位与 |
5 |
^ |
按位异或 |
4 |
| |
按位或 |
3 |
&& |
逻辑与 |
2 |
|| |
逻辑或 |
1 |
=,+=,-=,*=,%=,&=,^=,|=,<<=,>>= |
赋值,赋值且运算 |
四则运算练习
初级:
#!/bin/bash
read -p "请你输入数字1:" num1
read -p "请你输入数字2:" num2
read -n1 -p "请你输入运算符[+-*/]:" oper
["$oper"=="+"] && echo "$(($num1+$num2))" && exit
["$oper"=="-"] && echo "$(($num1-$num2))" && exit
["$oper"=="*"] && echo "$(($num1*$num2))" && exit
["$oper"=="/"] && echo "$(($num1/$num2))" && exit
echo "请输入正确的运算符"
-------------------------------------------------------------
变量的测试与内容测试
set -u
echo $i
蒙圈
环境变量配置文件
source 配置文件
. 配置文件
// 不重启的情况下重新加载配置文件
主要生效的环境变量配置文件有以下五个:
/etc/profile
/etc/profile.d/ *.sh
/etc/bashrc
~/.bash_profile
~/.bashrc
有两条路线,一条正常登陆路线,一条不用登陆的路线(子bash,su - user1)
用户登出登陆时,只会调用一个环境变量配置文件 ~/.bash_logout 默认没有任何内容,logout才行
~/.bash_history文件也就是历史命令保存文件
shell登陆信息
/etc/issue
// 可以支持的转义符我们可以通过man agetty命令查询 只对本地终端生效 加/l看序号
/etc/issue.net
/etc/ssh/sshd_config
Banner /etc/issue.net
// 远程连接的时候提示消息 ,但是不可以识别\转义符的信息了
/etc/motd
// 登陆成功后显示的欢迎信息 不论本地还是远程都显示 直接写就行
定义Bash快捷键
stty 关键字 快捷键
stty -a // 查询系统中创建的快捷键
// 可以改,但没必要
正则
大概只有shell会分两个正则
常见的是基础正则,直接grep就可以,扩展正则需要加-E或者使用egrep
基础正则
元字符 |
作用 |
* |
前一个字符匹配0次或任意多次 至少要加两个字符,不然全找出来 |
. |
匹配除了换行符外任意一个字符 |
^ |
匹配行首 |
$ |
匹配行尾 |
[] |
匹配中括号中指定的任意一个字符,只匹配一个字符 |
[^] |
匹配除中括号低字符意外的任意一个字符 |
\ |
转义符,用于取消特殊符号含义 |
\{n\} |
表示其前面的字符恰好出现n次 -E 的时候不需要加\ |
\{n,\} |
表示其前面的字符出现不小于n次 -E 的时候不需要加\ |
\{n,m\} |
表示其前面的字符至少出现n次,最多出现m次 -E 的时候不需要加\ |
正则符使用方法
grep 详细介绍 点这里
* :
grep "saaa*id" test.txt
// 查找saa"至少两个a"id ,
. :
grep "s..d" test.txt
// 找总共四个字母开头s结尾d中间两个任意的行
.* :
grep ".*" test.txt
// 匹配任意内容
^ :
grep "^A" test.txt
// 找开头第一个字母是A的行
$ :
grep "n$" test.txt
// 如果匹配以 . 结尾需要 grep "\.$" test.txt
^$ :
grep "^$" // test.txt
// 匹配空白行, grep -v "^$" test.txt 去除文件内的空白行 -v 取反
[] :
grep "s[ao]id" test.txt
// 查找s和id中间 a或o 也可以中间加一个 - 表示从哪到哪 grep "s[a-z]id" 1.txt
[^] :
grep "[^0-9]" test.txt
// 查找时不要有任意数字的行
\{n\} :
grep "a\{3\}" test.txt
// 查找a出现至少三次的行
grep "[0-9]\{3\}" test.txt
// 查找任意数字重复三次
grep "^[0-9]\{3\}[a-z]" test.txt
// 查找开头三位数字后面时字母的行
grep"[1][3-8][0-9]\{9\}" 1.txt
// 匹配手机号
\{n,\}
grep "[0-9]\{3,\}" test.txt
// 查找任意数字重复三次以上
\{n,m\}
grep "sa\{1,3\}i" test.txt
// 查找中间有1-3个a的sai
字符串模糊查询,\{n,m\}
扩展正则
扩展元字符 |
作用 |
+ |
前一个字符匹配1次或任意多次 |
? |
前一个字符匹配0次或一次 |
| |
匹配两个或多个分支选择 |
() |
匹配其整体为一个字符,即模式单元,可以理解为多个单个字符组成大字符 |
小例子
过滤邮箱:
grep -E "[0-9a-zA-Z]+@[0-9a-zA-Z_]+(\.[0-9a-zA-Z]+){1,3}" mail.txt
过滤ip:
看着头疼
字符串处理
cut
cut [选项] 文件名 // 使用tap键分隔,cut命令不识别 空格 !!!!
-f 列号 : 提取第几列,多列用 , 逗号隔开
-d 分隔符 : 按照指定分隔符分隔列
-c 字符范围 : 不依赖分隔符来区分列,而是通过字符范围(行首为0)来进行字段提取, n-表示从第n个字符到行尾;n-m从第n个字符到第m个字符; -m表示从第一个字符到第m个字符
例子:
grep "/bin/bash" /etc/passwd | grep -v "root" | cut -d ":" -f 1,3 /etc/passwd
// 查找能登陆的用户,取反不查找root 以:为分隔符,提取/etc/passwd文件的第一列和第三列 用户名和uid
awk编程
格式化输出
printf 格式化输出
printf '输出类型输出格式' 输出 // 注意这里是单引号
输出类型:
%ns: 输出字符串,n是数字代表输出几个字符
$ni: 输出整数,n是数字代表输出几个数字
$n.mf: 输出浮点数,n和m是数字,指代输出的整数位数和小数位数,如%8.2f,代表总共输出8位,其中两位小数,6位整数
输出格式:
\a: 输出警告声音
\b: 输出退格键,也就是backspace键
\f: 清除屏幕
\n: 换行
\r: 回车,Enter键
\t: 水平输出退格键,Tab键
\v: 垂直输出退格键,Tab键
student.txt
ID Name PHP Linux MySQL Average
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Tg 99 83 93 91.66
例子:
printf '%s' $(cat student.txt)
// 这样不行 IDNamePHPLinuxMySQLAverage1Liming82958687.662Sc74968785.663Tg99839391.66
printf '%s\t %s\t %s\t %s\t %s\t %s\t \n' $(cat student.txt)
// 这就跟cat 一样了
printf '%i\t %s\t %i\t %i\t %i\t %8.2f\t \n' $(cat student.txt | grep -v Name)
// 把id号和成绩改为整型平均成绩改为浮点, 并去掉Name这一行 -bash: printf: ID: invalid number 不然会这样报错
awk基础
awk '条件1{动作1} 条件2{动作2}....' 文件名 // 在awk中使用printf需要使用 双引号 动作就是指print或printf
条件:
看下方的表
动作:
格式化输出 printf或print 这两个的区别就是一个自动加换行符,一个需要手动加
流程控制语句
例子:
awk '{print $2 "\t" $6 }' student.txt
awk '{printf $2 "\t" $6 "\n"}' student.txt
// 列出第二列和第六列
df -h | grep "dev/sda3" | awk '{print $5}' | cut -d "%" f 1
// 查询容量 | 提取根的行 | 取出第五列 | 以%为分隔符 提取第一列
grep -v "Name" student.txt | awk '$6>=86 {print $2,$6}'
// 取反去掉含有Name的行 | 判断第六列的数据大于等于86就打印第二列和第六列
awk '$2 ~ /Sc/ {print $6}' student.txt
// 第二列是否包含 SC 如果包含就打印第六列
实现方法:
先判断有没有BEGIN,有就先执行BEGIN,然后一行一行的处理,把整行数据赋值给$0,第一列赋值给$1,第二列赋值给$2,第三列赋值给$3......有判断条件就判断后执行 ,有END就执行END
条件的类型 |
条件 |
说明 |
awk保留字 |
BEGIN{} |
在awk程序一开始时,尚未读取任何数据之前执行,BEGIN后的动作只在程序开始时执行一次 |
|
END{} |
在awk程序处理完所有数据,即将结束时执行,END后的动作只在程序结束时执行一次 |
关系运算符 |
> |
大于 |
|
< |
小于 |
|
>= |
大于等于 |
|
<= |
小于等于 |
|
== |
等于,用于判断两个值是否相等,如果是给变量赋值,用= |
|
!= |
不等于 |
|
A~B |
判断字符串A中是否包含匹配B表达式的子字符串 |
|
A!~B |
判断字符串A中是否不包含能匹配B表达式的子字符串 |
正则表达式 |
/正则/ |
如果在"//"中可以写入字符,也可以支持正则表达式 |
awk内置变量
awk内置变量 |
作用 |
$0 |
代表目前awk所读入的整行数据,我们已知awk时一行一行读入数据的,$0就代表当前读入行的整行数据 |
$n |
代表目前读入行的第n列 (字段) |
*NF |
当前行拥有的列数 |
*NR |
当前awk所处理的行,是总数据的第几行 |
*FS |
用户自定义分隔符,awk默认分隔符是任何空格,如果想要使用其他分隔符,就需要FS变量定义 |
ARGC |
命令行参数个数 |
ARGV |
命令好参数数组 |
FNR |
当前文件中的当前记录数(对输入文件起始为1) |
OFMT |
数值的输出格式(默认为%.6g) |
OFS |
输出列(字段)的分隔符(默认为空格) |
ORS |
输出行(记录)的分隔符(默认为换行符) |
RS |
输入行(记录)分隔符(默认为换行符) |
*为常用
进阶例子:
cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN{FS=":"} $3="500" {print $1}'
// 查看 passwd文件 | 找出含有 /bin/bash的行 | awk 执行开始前 把分隔符换成 : 第三列=500 就打印第一列
cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN{FS=":"} {print $1 $1"\t" NR "\t" NF}'
// 查看 passwd文件 | 找出含有 /bin/bash的行 | awk 执行开始前 把分隔符换成 : 打印第1列 tab 当前的行 tab 总列数
sed
sed 主要是用来将数据进行选取,替换,删除,新增的命令
sed [选项] '[动作]' 文件名
选项:
-n : 一般sed命令会把所有的数据都输出到屏幕,如果加入此选择,则只会把经过sed命令处理的行输出到屏幕
-e : 允许对输入数据应用多条sed命令编辑,中间用 ; 隔开
-f 脚本文件名 : 从sed 脚本中读入sed操作,和awk -f 类似
-r : 在sed 中支持扩展正则表达式
-i : 用sed 的修改结果直接修改读取数据的文件,而不是由屏幕输出动作
动作:
a \ : 追加,在当前行后添加一行或多行,添加多行时,除最后一行外,每行末尾需要用 \ 代表数据未完结
c \ : 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾用 \ 代表数据未完结
i \ : 插入,唉当前行前插入一行或多行,插入多行时,除最后一行外,每行末尾用 \ 代表数据未完结
d : 删除 ,删除指定的行
p : 打印输出指定的行
s : 字符替换,用一个字符串替换另外一个字符串,格式为 " 行范围 s/旧字串/新字串/g" (和vim中的替换格式类似)
例子:
sed -n '2p' student.txt
// 不加-n 会全部输出
sed '2,4d' student.txt
// 打印剩余行,并没有写入文件
sed -i '2a 111111111111' student.txt
// 追加内容,指定行的后面,执行后不会打印出来,所以cat看一下
sed '2i hello \
> word' student.txt
// 一次添加多行
sed '3c 4 zyx 11 22 33 22' student.txt
// 替换,把第三行换成3c 后面的内容
sed -e '3d ; 4d' student.txt
// -e多条编辑 用; 隔开
sed -e '3d \
> 4d ' student.txt
// 如果换行了可以不用写 ;
sed 's/Lm/zyx/g' student.txt
// 字符替换
sed '4s/^/#/g' student.txt
// 替换行首为# 也就是注释指定行
sort
排序命令sort
sort [选项] 文件名
-f : 忽略大小写
-b : 忽略每行前面的空白部分
-n : 以数值型进行排序,默认使用字符串型排序
-r : 反向排序
-u : 删除重复行,就是uniq命令
-t : 指定分隔符,默认分隔符是制表符 tap
-k : 指定字段,是一个范围,如果第三列就是 -k 3,3
例子:
sort /etc/passwd
// 直接排序,按每行第一个字符来排序
sort -t ":" -k 3,3 -n /etc/passwd
uniq [选项] 文件名
-i : 忽略大小写
// 用来取消重复行的命令,和sort -u一样
条件判断
test
按照文件类型进行判断*
测试选项 |
作用 |
-b 文件 |
判断该文件是否存在,并且是否为块设备文件,是就为真 |
-c 文件 |
判断该文件是否存在,并且是否为字符设备文件,是就为真 |
-d 文件* |
判断该文件是否存在,并且是否为目录文件,是就为真 |
-e 文件* |
判断该文件是否存在,是就为真 |
-f 文件* |
判断该文件是否存在,并且是否为普通文件,是就为真 |
-L 文件* |
判断该文件是否存在,并且是否为符号链接文件,是就为真 |
-p 文件 |
判断该文件是否存在,并且是否为管道文件,是就为真 |
-s 文件 |
判断该文件是否存在,并且是否为非空,非空为真 |
-S 文件 |
判断该文件是否存在,并且是否为套接字文件 ,是为真 |
*为常用
[ -e ip.txt] 或者 test -e ip.txt
echo $? // 查看上一条命令执行结果
0 // 0为成功,非零为失败
按照文件权限进行判断*
测试选项 |
作用 |
-r 文件 |
判断该文件是否存在,并且是否该文件拥有读权限 r 有为真 |
-w 文件 |
判断该文件是否存在,并且是否该文件拥有写权限 w 有为真 |
-x 文件 |
判断该文件是否存在,并且是否该文件拥有执行权限 x 有为真 |
-u 文件 |
判断该文件是否存在,并且是否该文件拥有SUID权限 有为真 |
-g 文件 |
判断该文件是否存在,并且是否该文件拥有SGID权限 有为真 |
-k 文件 |
判断该文件是否存在,并且是否该文件拥有SBit权限 有为真 |
两个文件直接比较
测试选项 |
作用 |
文件1 -nt 文件2 |
判断文件1的修改时间是否比文件2的新 新则为真 |
文件1 -ot 文件2 |
判断文件1的修改时间是否比文件2的旧 旧则为真 |
文件1 -ef 文件2 |
判断文件1 是否和文件2的Inode号一致,可以理解为两个文件是否为同一个文件,判断硬链接 |
两个整数之间比较*
测试选项 |
作用 |
整数1 -eq 整数2 |
判断整数1是否和整数2相等 相等为真 |
整数1 -ne 整数2 |
判断整数1是否和整数2不相等, 不相等为真 |
整数1 -gt 整数2 |
判断整数1是否大于整数2,大于为真 |
整数1 -lt 整数2 |
判断整数1是否小于整数2,小于为真 |
整数1 -ge 整数2 |
判断整数1是否大于等一整数2 ,大于等于为真 |
整数1 -le 整数2 |
判断整数1是否小于等于整数2 |
字符串判断*
测试选项 |
作用 |
-z 字符串 |
判断字符串是否为空 为空为真 |
-n 字符串 |
判断字符串是否为非空 非空为真 |
字串1 == 字串2 |
判断字符串1是否和字符串2相等 相等为真 |
字串1!=字串2 |
判断字符串1是否和字符串2 不相等 不相等为真 |
多重条件判断*
测试选项 |
作用 |
判断1 -a 判断2 |
逻辑与,判断1和判断2都为真,最终结果才为真 |
判断1 -o 判断2 |
逻辑或,判断1 和判断2 有一个成立,最终结果就为真 |
! 判断 |
逻辑非,使原始的判断式取反 |
流程控制语句
if条件判断
单分支if条件语句
if [ 条件判断式 ] ; then
程序
fi
注意:
- if语句使用fi结尾,和一般语言使用大括号的结尾不同
- [ 条件判断式 ] 就是使用test命令判断,所以中括号和条件判断式之间必须有空格
- then后面跟符合条件之后执行的程序,可以放在[]之后,用 ; 分隔,也可以换行写入
if [条件判断式 ]
then
程序
fi
例子:
判断根目录使用率超过了80%
#!/bin/bash
aa=$(df -h | grep /dev/sda3 | awk ' {print $5}' | cut -d "%" -f 1)
if [ "$aa" -ge 80 ]
then
echo "根分区占用率已经超过了80 ,请注意"
if
双分支if条件语句
if [ 田间判断式 ]
then
条件成立时, 执行的程序
else
条件不成立时,执行的另一个程序
fi
例子:
数据库mysql备份
#!/bin/bash
ntpdate asia.pool.ntp.org &>/dev/null
#同步系统时间
date=$(date +%y%m%d)
# 把当前系统时间按照 年月日格式赋予变量date
size=$(du -sh /var/lib/mysql)
$ 统计mysql数据库的大小
if [ -d /tmp/dbbak ]
# 判断备份目录是否存在,是否为目录
then
#如果判断为真,执行以下脚本
echo " Date : $date!" > /tmp/dbbak/dbifo.txt
echo " Date size : $size" >> /tmp/dbbak/dbifo.txt
# 把当前日期和数据库大小保存入临时文件
cd /tmp/dbbak
# 进入备份目录
tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>/dev/null
# 打包压缩数据库与临时文件,把所有输出丢入垃圾箱(不想看到任何正确输出,如果出现输出就是报错)
rm -rf /tmp/dbbak/dbinfo.txt
# 删除临时文件
else
mkdir /tmp/dbbak
# 如果判断为假,则建立备份目录
echo " Date : $date!" > /tmp/dbbak/dbifo.txt
echo " Date size : $size" >> /tmp/dbbak/dbifo.txt
# 把当前日期和数据库大小保存入临时文件
cd /tmp/dbbak
# 进入备份目录
tar -zcf mysql-lib-$date.tar.gz /var/lib/mysql dbinfo.txt &>/dev/null
# 打包压缩数据库与临时文件,把所有输出丢入垃圾箱(不想看到任何正确输出,如果出现输出就是报错)
rm -rf /tmp/dbbak/dbinfo.txt
# 删除临时文件
fi
例子2:
判断apche是否启动,如果没有启动则自动启动
#!/bin/bash
aa=$( netstat -tuln | awk '{print $4}' | grep ":80$" )
if [ "$aa" == " " ]
then
echo " httpd is down ,must restart "
/etc/rc.d/init.d/httpd start $> /dev/null
else
echo "http is ok"
fi