02-三剑客命令grep、sed、awk
1. grep命令
作用:作用是在文件中提取和匹配符合条件的字符串
[root@localhost ~]# grep [选项] "搜索内容" 文件名
-c | 计算找到‘搜索字符串’的行数 |
---|---|
-o | 指输出匹配的内容 |
-i | 不区分大小写 |
-n | 显示匹配内容的行号 |
-r | 当指定要查找的是目录而非文件时,必须使用这项参数,也就是递在目录中归查找内容 |
-v | 反向选择,即没有‘搜索字符串’内容的行 |
-E | 扩展 grep,即 egrep,可以使用扩展正则表达式 |
-l | 列出文件内容符合指定的范本样式的文件名称 |
--color=auto | 搜索关键词显示颜色 |
-V | 显示软件版本信息 |
案例:
# 从tesh.sh中查找包含echo行的信息
[root@localhost ~]# grep "echo" test.sh
# 从tesh.sh中查找包含echo行的信息,只统计行数
[root@localhost ~]# grep -c "echo" test.sh
5
2. Shell常见通配符
用于匹配文件名,完全匹配
通 配 符 | 作 用 |
---|---|
? | 匹配一个任意字符 |
* | 匹配0个或任意多个任意字符,也就是可以匹配任何内容 |
[] | 匹配中括号中任意一个字符。例如,[abc]代表一定匹配一个字符,或者是a,或者是b,或者是c |
[-] | 匹配中括号中任意一个字符,-代表一个范围。例如,[a-z]代表匹配一个小写字母 |
[^] | 逻辑非,表示匹配不是中括号内的一个字符。例如,[^0-9]代表匹配一个不是数字的字符 |
练习:
[root@localhost ~]# touch abc abcd acc acd bcd bbbde 123a 234d b453 a_c abccd
[root@localhost ~]# ls
123a 234d abc abcd acc a_c acd b453 bbbde bcd abccd
# 查找文件名为abc的文件,精确查找
[root@localhost ~]# find ./ -type f -name "abc"
./abc
# 查找包含文件名为abc的文件,模糊查找
[root@localhost ~]# find ./ -type f -name "abc*"
./abc
./abcd
./abccd
# 查找a和c的中间为任意一个字符的文件
[root@localhost ~]# find ./ -type f -name "a?c"
./abc
./acc
./a_c
# 查找a和c中间只能是a b _其中任意一个字符的文件
[root@localhost ~]# find ./ -type f -name "a[bc_]c"
./abc
./acc
./a_c
# 查找a和c中间只能是小写字母其中任意一个字符的文件
[root@localhost ~]# find ./ -type f -name "a[a-z]c"
./abc
./acc
# 查找cd前面是任意一个小写字母的文件
[root@localhost ~]# find ./ -type f -name "[a-z]cd"
./acd
./bcd
# 查找a和c中间不包含字母的文件
[root@localhost ~]# find ./ -type f -name "a[^a-z]c"
./a_c
3. 基础正则
用于匹配字符串,包含匹配
元字符 | 作 用 |
---|---|
* | 前一个字符匹配0次或任意多次。 |
. | 匹配除了换行符外任意一个字符 |
^ | 匹配行首。例如:^hello会匹配以hello开头的行。 |
$ | 匹配行尾。例如:hello&会匹配以hello结尾的行 |
[] | 匹配中括号中指定的任意一个字符,只匹配一个字符。例如:[aoeiu] 匹配任意一个元音字母,[0-9] 匹配任意一位数字, [a-z]、[0-9]匹配小写字和一位数字构成的两位字符。 |
[^] | 匹配除中括号的字符以外的任意一个字符。例如:[^0-9] 匹配任意一位非数字字符,[^a-z] 表示任意一位非小写字母。 |
\ | 转义符。用于取消讲特殊符号的含义取消 |
表示其前面的字符恰好出现n次。例如:[0-9]{4} 匹配4位数字,[1][3-8][0-9]{9} 匹配手机号码。 | |
表示其前面的字符出现不小于n次。例如: [0-9]{2,} 表示两位及以上的数字 | |
表示其前面的字符至少出现n次,最多出现m次。例如: [a-z]{6,8} 匹配6到8位的小写字母。 |
4. sed命令
字符流编辑工具(行编辑工具)==按照每行中的字符进行处理操作
命令格式: sed [选项] ‘[动作]’ 文件名
命令作用:
- 擅长对行进行操作处理
- 擅长将文件的内容信息进行修改调整/删除
具体功能作用:
- 文件中添加信息的能力 (增)
- 文件中删除信息的能力 (删)
- 文件中修改信息的能力 (改)
- 文件中查询信息的能力 (查)
选项:
选项参数 | 作用 |
---|---|
-n | sed命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过sed命令处理的行输出到屏幕 |
-e | 允许对输入数据应用多条sed命令编辑 |
-r | 在sed中支持扩展正则表达式 |
-i | 用sed的修改结果直接修改读取数据的文件,而不是由屏幕输出,写入磁盘 |
动作:
p print | 输出指定的行 |
---|---|
i insert | 插入信息,在指定信息前面插入新的信息 |
a append | 附加信息,在指定信息后面附加新的信息 |
d delete | 删除指定信息 |
s substitute | 替换信息 s#旧信息#新信息#g(全局替换) |
c | 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结。 |
sed命令 练习:
# 准备练习内容
[root@zabbix linux_study]# cat a.txt
name age gender qq
pyhton 23 F 12324214214
linux 44 M 44454667
java 99 F 98989898
C 89 F 889877666
c++ 78 M 8797665599
### 根据文件内容的行号进行查询
# 显示指定行号信息
[root@zabbix linux_study]# sed -n "1p" a.txt
name age gender qq
# 根据行号信息,输出多行内容(连续)
[root@zabbix linux_study]# sed -n "1,3p" a.txt
name age gender qq
pyhton 23 F 12324214214
linux 44 M 44454667
# 根据行号信息,输出多行内容(不连续)
[root@zabbix linux_study]# sed -n "1p;4p" a.txt
name age gender qq
java 99 F 98989898
### 根据文件内容的信息进行查询:
# 根据内容信息,输出单行内容
[root@zabbix linux_study]# sed -n "/linux/p" a.txt
linux 44 M 44454667
# 根据内容信息,输出多行内容(连续)
[root@zabbix linux_study]# sed -n "/python/,/java/p" a.txt
python 23 F 12324214214
linux 44 M 44454667
java 99 F 98989898
# 根据内容信息,输出多行内容(不连续)
[root@zabbix linux_study]# sed -n "/python/p;/java/p" a.txt
python 23 F 12324214214
java 99 F 98989898
### sed添加信息 如果要真实修改文件内容,加上-i参数,-i和-n参不能同时使用
# 在第二行添加[root@zabbix linux_study]# sed -r "2ic#\t99\t989988" a.txt
name age gender qq
c# 99 989988
python 23 F 12324214214
linux 44 M 44454667
java 99 F 98989898
C 89 F 889877666
c++ 78 M 8797665599
# 在最后一行添加
[root@zabbix linux_study]# sed -r "\$ac#\t99\tF\t989988" a.txt
name age gender qq
python 23 F 12324214214
linux 44 M 44454667
java 99 F 98989898
C 89 F 889877666
c++ 78 M 8797665599
c# 99 F 989988
# 在第二行后面添加
[root@zabbix linux_study]# sed -r "2ac#\t99\tF\t989988" a.txt
name age gender qq
python 23 F 12324214214
c# 99 F 989988
linux 44 M 44454667
java 99 F 98989898
C 89 F 889877666
c++ 78 M 8797665599
### sed删除信息 如果要真是删除信息,加上-i参数
# 删除指定行信息
[root@zabbix linux_study]# sed "2d" a.txt
name age gender qq
linux 44 M 44454667
java 99 F 98989898
C 89 F 889877666
c++ 78 M 8797665599
# 删除文件中第2行到第4行内容
[root@zabbix linux_study]# sed "2,4d" a.txt
name age gender qq
C 89 F 889877666
c++ 78 M 8797665599
#删除文件中第2行到第4行内容
[root@zabbix linux_study]# sed "2d;4d" a.txt
name age gender qq
linux 44 M 44454667
C 89 F 889877666
c++ 78 M 8797665599
#删除有linux行的信息
[root@zabbix linux_study]# sed "/linux/d" a.txt
name age gender qq
python 23 F 12324214214
java 99 F 98989898
C 89 F 889877666
c++ 78 M 8797665599
### sed修改信息,把含有python的行的python改成harris
[root@zabbix linux_study]# sed "s#python#harris#g" a.txt
name age gender qq
harris 23 F 12324214214
linux 44 M 44454667
java 99 F 98989898
C 89 F 889877666
c++ 78 M 8797665599
5. awk编程
printf格式化输出
[root@m01 ~]# printf '输出类型输出格式' 输出内容
输出类型:
%ns: 输出字符串。n 是数字指代输出几个字符
%ni: 输出整数。n 是数字指代输出几个数字
%m.nf:输出浮点数。m 和 n 是数字,指代输出的整数位数和小数位数。 如%8.2f 代表共输出 8 位数,其中 2 位是小数,6 位是整数。
输出格式:
\n: 换行
\t: 水平输出退格键,也就是 Tab 键
\a: 输出警告声音
\b: 输出退格键,也就是 Backspace 键
\f: 清除屏幕
\r: 回车,也就是 Enter 键
\v: 垂直输出退格键,也就是 Tab 键
### 格式输出
[root@m01 ~]# printf 'name\t age\t gender\n test\t 23\t 男\n'
name age gender
test 23 男
[root@m01 ~]# printf 'name\tage\tgender\taverage\n%s\t%2i\t%s\t%4.2f\n' test 22 F 22.12
name age gender average
test 22 F 22.12
简介:擅长对列进行操作和进行数据信息的统计,AWK是一种处理文本文件的语言,是一个强大的文本分析工具
命令作用:
1. 排除信息
2. 查询信息
3. 统计信息
4. 替换信息
命令格式: awk [选项参数] '条件1{动作1} 条件2{动作2} 文件名
-
选项参数说明:
- -F fs or --field-separator fs
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。 - -v var=value or --asign var=value
赋值一个用户定义变量。 - -f scripfile or --file scriptfile
从脚本文件中读取awk命令。 - -mf nnn and -mr nnn
对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。 - -W compact or --compat, -W traditional or --traditional
在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。 - -W copyleft or --copyleft, -W copyright or --copyright
打印简短的版权信息。 - -W help or --help, -W usage or --usage
打印全部awk选项和每个选项的简短说明。 - -W lint or --lint
打印不能向传统unix平台移植的结构的警告。 - -W lint-old or --lint-old
打印关于不能向传统unix平台移植的结构的警告。 - -W posix
打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符和=不能代替和=;fflush无效。 - -W re-interval or --re-inerval
允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。 - -W source program-text or --source program-text
使用program-text作为源代码,可与-f命令混用。 - -W version or --version
打印bug报告信息的版本。
- -F fs or --field-separator fs
-
条件
awk保留字 BEGIN 在 awk 程序一开始时,尚未读取任何数据之前执行 END 在 awk 程序处理完所有数据,即将结束时执行 关系运算符 > 大于 < 小于 >= 大于等于 <= 小于等于 == 等于。用于判断两个值是否相等,如果是给变量赋值,使用 “=”号 != 不等于 A~B 判断字符串 A 中是否包含能匹配 B 表达式的子字符串 A!~B 判断字符串 A 中是否不包含能匹配 B 表达式的子字符串 正则表达式 /正则/ 在“//”中可以写入字符,也可以写正则表达式 -
动作
- 格式化输出
- 流程控制语句
awk内置变量
$0 | 代表目前 awk 所读入的整行数据。我们已知 awk 是一行一行读入数据 的,$0 就代表当前读入行的整行数据 |
---|---|
$n | 代表目前读入行的第 n 个字段。 |
NR | 当前 awk 所处理的行,是总数据的第几行 |
NF | 当前行拥有的字段(列)总数, ($NF-n)表示倒数第n列 |
FS | 用户定义分隔符。awk 的默认分隔符是任何空格,如果想要使用其他 分隔符(如“:”),就需要 FS 变量定义 |
ARGC | 命令行参数个数 |
ARGV | 命令行参数数组 |
FNR | 当前文件中的当前记录数(对输入文件起始为 1) |
OFMT | 数值的输出格式(默认为%.6g) |
OFS | 输出字段的分隔符(默认为空格) |
RS | 输入记录分隔符(默认为换行符) |
ORS | 输出记录分隔符(默认为换行符) |
练习
## 练习环境准备
[root@m01 ~]# cat > test.txt << EOF
> 姓 名 ID 捐款记录
> Zhang Dandan 41117397 :250:100:175
> Zhang Xiaoyu 390320151 :155:90:201
> Meng Feixue 80042789 :250:60:50
> Wu Waiwai 70271111 :250:80:75
> Liu Bingbing 41117483 :250:100:175
> Wang Xiaoai 3515064655 :50:95:135
> Zi Gege 1986787350 :250:168:200
> Li Youjiu 918391635 :175:75:300
> Lao Nanhai 918391635 :250:100:175
> EOF
## 查询信息
逗号,表示连续的显示一段行号开头的信息
分号;表示指定行号显示
# NR:查询指定第几行信息
[root@m01 ~]# awk 'NR==2' t1.txt
Zhang Xiaoyu 390320151 :155:90:201
# 查询第2到第4行的信息
[root@m01 ~]# awk 'NR==2,NR==4' t1.txt
Zhang Xiaoyu 390320151 :155:90:201
Meng Feixue 80042789 :250:60:50
Wu Waiwai 70271111 :250:80:75
# 查询第1行、第4行的信息
[root@m01 ~]# awk 'NR==1;NR==4' t1.txt
Zhang Dandan 41117397 :250:100:175
Wu Waiwai 70271111 :250:80:75
# 使用//查询
[root@m01 ~]# awk '/Zhang/' t1.txt
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
# 查询Zhang、Lao所在的行信息
[root@m01 ~]# awk '/Zhang/;/Lao/' t1.txt
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
Lao Nanhai 918391635 :250:100:175
# 显示Zhang的ID号
[root@m01 ~]# awk '/Zhang/ {printf $3"\n"}' t1.txt
41117397
390320151
# 显示Zhang的捐款记录,$
[root@m01 ~]# awk '/Zhang/ {printf $NF"\n"}' t1.txt
:250:100:175
:155:90:201
# 显示所有以41开头的ID号码的人的全名和ID号码
[root@m01 ~]# awk '$3~/^41/{print $1,$2,$3}' t1.txt
Zhang Dandan 41117397
Liu Bingbing 41117483
# 显示所有ID号码最后一位数字是1或5的人的全名
[root@m01 ~]# awk '$3~/1$|5$/ {print $1,$2}' t1.txt |column -t
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai
# awk默认使用空格分割,使用-F指定分割符
[root@m01 ~]# awk '/Zhang/{print $NF}' t1.txt|awk -F ":" '{print $3}'
100
90
# BEGIN在最开始的时候执行,读取文件,NED在最后执行
[root@m01 ~]# awk '/Zhang/ {print $NF}' t1.txt |awk 'BEGIN{FS=":"}{print $3}END{print "我是最后执行的"}'
100
90
我是最后执行的
## 替换信息
# gsub(/需要替换的信息/,"修改成什么信息",将哪列信息进行修改)
[root@m01 ~]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$NF);print $NF}' t1.txt
$155$90$201
awk '$0~/^$/ {gsub(/ /,/"-"/)};print $0'
## 排除信息
# 件中空行进行排除、文件中注释信息进行排除
[root@m01 ~]# cat t1.txt
姓 名 ID 捐款记录
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
#Meng Feixue 80042789 :250:60:50
Wu Waiwai 70271111 :250:80:75
Liu Bingbing 41117483 :250:100:175
-----------------------------------------
Wang Xiaoai 3515064655 :50:95:135
Zi Gege 1986787350 :250:168:200
-----------------------------------------
Li Youjiu 918391635 :175:75:300
-----------------------------------------
Lao Nanhai 918391635 :250:100:175
-----------------------------------------
# 排除所有以#和-开头的信息
[root@m01 ~]# awk '$0!~/^#|^-/' t1.txt
姓 名 ID 捐款记录
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
Wu Waiwai 70271111 :250:80:75
Liu Bingbing 41117483 :250:100:175
Wang Xiaoai 3515064655 :50:95:135
Zi Gege 1986787350 :250:168:200
Li Youjiu 918391635 :175:75:300
Lao Nanhai 918391635 :250:100:175
## 统计信息
# 统计/etc/services文件中有井号开头的行
[root@m01 ~]# awk '/^#/{i++}END{print i}' /etc/services
102
# 统计系统中有多少个虚拟用户 普通用户
[root@m01 ~]# awk '$NF~/bash/{i=i+1}END{print i}' /etc/passwd
63
# 虚拟用户数量
[root@m01 ~]# awk '$NF!~/bash/{i=i+1}END{print i}' /etc/passwd
22
awk函数
awk 编程也允许在编程时使用函数
: << !
function 函数名(参数列表){
函数体
}
!
# 删除t1.txt文件中的-
[root@localhost ~]# sed '/-/d' t1.txt -i
# 定义函数 test ,包含两个参数,函数体的内容是输出这两个参数,函数体是打印两个参数
# 调用函数 test ,并向两个参数传递值。
[root@m01 ~]# awk 'function test(a,b){printf a"\t"b"\n"} { test($1,$2) }' t1.txt |column -t
姓 名
Zhang Dandan
Zhang Xiaoyu
#Meng Feixue
Wu Waiwai
Liu Bingbing
Zi Gege
Wang Xiaoai
Zi Gege
Li Youjiu
Lao Nanhai
awk调用脚本
对于小的单行程序来说,将脚本作为命令传递给 awk 是非常简单的,而对于多行程序就比较难处理。当程序是多行的时候,使用外部脚本是很适合的。首先在外部文件中写好脚本,然后可 以使用 awk 的-f
选项,使其读入脚本并且执行。
[root@m01 ~]# cat awk.sh
#!/bin/bash
BEGIN{FS=":"}$3>=1000{print $0}
# 查找普通用户
[root@m01 ~]# awk -f awk.sh /etc/passwd
python:x:1000:1000:python:/home/python:/bin/bash
linux:x:1002:1002::/home/linux:/bin/bash
java:x:1003:1003::/home/java:/bin/bash
6. 管道命令 |
命令 1 的正确输出的结果作为命令 2 的操作对象
# 查看所有/etc下的文件,从中过滤包含yum的文件
[root@m01 ~]# ll /etc | grep yum
drwxr-xr-x. 6 root root 100 Dec 30 16:36 yum
-rw-r--r-- 1 root root 970 May 25 10:59 yum.conf
drwxr-xr-x. 2 root root 4096 Jun 1 14:29 yum.repos.d
#查看22远程端口是否开启
[root@m01 ~]# netstat -tulnp |grep 22
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 985/sshd
tcp6 0 0 :::22 :::* LISTEN 985/sshd
大多数人想要改造这个世界,但却罕有人想改造自己。未曾失败的人恐怕也未曾成功过。