-
文本处理:
vim,vi
sed,awk,grep
cut,cat,tr,uniq,sort,comm
一、sed
(1)原理
非交互式的编辑器
流式
执行流程:read ==> excute ==>print(打印) ==>repeat
(2)语法:
格式一:sed 选项 '[定址符]命令' 文件
格式二:前置命令 | sed 选项 '[定址符]命令' 文件
(3)打印
-n:不打印模式空间
例: sed -n '/^root/,/^apache/ p' /etc/passwd 从一行到另一行之间所有的行
sed -n 'm,/^apache/ p' /etc/passwd 从m行到apache开头的行的所有
sed -n 'm,n p' /etc/passwd 从第m行到n行的所有行
sed -n '/^root/,n p' /etc/passwd 从root开头的行以及往下数n行
sed -n '$ p' /etc/passwd 显示最后一行
sed -n 'm~a p' /etc/passwd(a:步长) 从m行开始每隔a行显示
(4)多点编辑问题 ---(查找passwd中以root和apache开头的行)
① -e: ( \ ,{} )断行
例:\:
sed -n \
> -e '/^root/p' \
> -e '/^apache/p' \
> /etc/passwd
结果:
root:x:0:0:root:/root:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
{}:
sed -n '{
> /^root/ p
> /^apache/ p
> }' /etc/passwd
② - f:文本
例: [root@localhost test2]# cat com.txt
/^root/p
/^apache/ p
[root@localhost test2]# sed -n -f com.txt /etc/passwd
(5)删除
d
例: sed '/^root/ d' /etc/passwd 删除root开头的行
sed '2,3 d' /etc/passwd 删除2-3行
sed '/^root/,3 d'/etc/passwd 删除从root开始的的3行
sed '3, /^apache// d' /etc/passwd 删除第3行到apache开头的行
sed '/^root/,+3 d'/etc/passwd 删除算root开始向后在加的3行
sed '/^$/ d'/etc/passwd 删除空行
sed '/^#/d'/etc/passwd 删除以#开头的行
(6)读写
sed '1 r b.txt' a.txt 在a.txt文件的第一行下面插入b.txt
sed '1 w c.txt' a.txt 将c.xt中的第一行另存为a.txt
sed '/^102/,/^103/ r b.txt' test1 在test1中以102到103开头的行下都插入b.txt
sed '/^102/,3 r b.txt' test1 在test1中以102到1第三行下都插入b.txt
sed '1,3 r b.txt' test1 在test1中第一行到第三行下都插入b.txt
(7)替换
sed '/^x/s/旧/新' 文件名
例:
- sed '2 s/old/new/'/etc/passwd 把2行第一个old改为new
- sed '2,5 s/old/new/'/etc/passwd 把2-5行第一个old改为new
- sed '2,5 s/old/new/g'/etc/passwd 把2-5行所有old改为new
- sed '2,5 s/old/new/i'/etc/passwd 把2-5行第一个old改为new不区分大小写
- sed '2,5 s/old/new/w d.txt'/etc/passwd 把2-5行第一个old改为new 并写入到d.txt文件里
先在b.txt中写上想要查的文件的路径 /etc/passwd /etc/shadow
- sed 's/^/ls -l /e'/etc/passwd 相当于 ls -l /etc/passwd;ls-l /etc/shadow
- sed 's/^.*/<&>/g' passwd 把文件passwd中每一行都用<>框起来
- sed 's/^[0-9][0-9][0-9]/[&]/g' passwd 把文件中三位数字开头的数字用[]框起来
(8)后项引用
- sed 's/\([^,]*\).*/\1/g' test 显示匹配每一行 开头逗号结尾第一个部分
101
102
103
104
105
- sed 's/\([^:]*\).*/\1/' /etc/passwd (分组) 截取以:为一个分段中的第一段
- echo "This Is a Test" |sed 's/\(\b[A-Z]\)/\(\1\)/g'
把This Is a Test写入到文件中并匹配单词开始或结束为A-Z的用()括起来
(T)his (I)s a (T)est
- cat numbers.txt
- 1
12
123
1234
12345
123456- sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers.txt
分为3个组,第一组为开头或以0-9数字开头一次;第二组为0-9的数字一次或多次;第三组为0-9的数字三次
从后往前分析,先匹配第三组三位数,与一二组用逗号隔开
1
12
123
1,234
12,345
123,456
- sed 's/^\([^,]*\),\([^,]*\),\([^,]*\)/\1,\3/' test 分为三组,显示第一组和第三组用逗号连接
101,CEO
102,IT Manager
103,Sysadmin
104,Developer
105,Sales Manager
(9)文本块
c 替换当前
[root@localhost test2]# sed '/^GATEWAY/ c GATEWAY=192.168.42.2' ifcfg-eth0
i 行前插入
[root@localhost test2]# sed '/^GATEWAY/ i DNS2=8.8.4.4' ifcfg-eth0
a 行后插入文本
[root@localhost test2]# sed '/^GATEWAY/ a DNS1=8.8.8,8' ifcfg-eth0
[root@localhost test2]# sed '1 a DNS1=8.8.8,8' ifcfg-eth0 在第一行后插入
[root@localhost test2]# sed '$ a DNS1=8.8.8,8' ifcfg-eth0 在最后一行插入
(10)sed 中的正则
- 用户提权:
(1)su
普通用户的su进制,PAM机制(P433)
gpasswd -a username wheel :all root
(2)sudo
三个分组:用户 命令 主机
cd /etc/sudoers.d 写入一个文件 test 关于用户提权
前三行为用户test1有权利修改ip,使用别名实现,且不需要输入密码
第四行为test1拥有权限使用/usr/sbin下的所有命令,但没有删除用户的权限
第五行为test1拥有查看/var/log/message*下的所有文件,并且避免查看其他文件
(3)LADP 统一身份认证
扩展堡垒机(jumpserver)
二、awk
- 语法
- awk [参数] 'BEGIN{}//{print $1} END{}' file
- comm |awk [参数] ‘BEGIN{} // {print $1} END{}'
-F | 指明输入时用到的字段分隔符 |
-v var=value | 自定义变量 |
① -F
- awk -F: '/root/' passwd 显示出含有root的行
- awk -F: '{print $1}' passwd 显示出以:为分隔符的第一部分
- awk -F: '/root/{print $1,$3}' passwd 显示出含root以:为分隔符的第一,三部分
- awk 'BEGIN{FS=":"} /^root/{print $1,$3}' passwd
- awk -F',' '{print $2$3}' 3.txt 显示出以逗号为分隔符的二三部分
- awk -F',' '{print $2':'$3}' 3.txt 显示出以逗号为分隔符的二三部分之间用冒号分隔
- awk -F ',' 'BEGIN{OFS=":"}{print $2,$3}' 3.txt
- df -P |grep '/'|awk '$4 > 25000{print $4}'
字符串常量
\ | 反斜线 |
\a | altert字符,通常为ASCII BEL字符 |
\b | 退格键 |
\f | 换页 |
\n | 换行符 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\c | 字符由十六进制数字下面的\x中的字符串来表示 |
\xhex digits | 字面字符c |
- awk -F: 'BEGIN{print "username \n-------------\n"} /root/ {print $1} END {print "-----------"}' passwd
显示含有root的行的以冒号为分隔符的第一部分在这前一行插入username换行符-----换行符,末尾插入-------
- awk -F: '{print $1"\t"$3}' passwd
显示passwd中第一部分和第三部分中间的空格水平制表符显示
格式化输出
%c | 显示字符的ASCII码 | |
%d, %i | 显示十进制整数 | |
%e, %E | 显示科学计数法数值 | |
%f: | 显示为浮点数 | |
%g, %G | 以科学计数法或浮点形式显示数值 | |
%s | 显示字符串 | |
%u | 无符号整数 | |
%% | 显示%自身 | |
- | 左对齐(默认右对齐) %-15s | |
+ | 显示数值的正负符号 %+d | |
printf: | 格式化输出,默认不会自动换行 |
- awk -F: '{printf "%s",$1}' passwd 格式输出文件中第一部分的字符串,输出为一行
- awk -F: '{printf "%-20s %10d\n",$1,$3}' passwd 文件中第一部分以字符串形式左对齐,第三部分以十进制右对齐格式化输出
- awk -F: '{printf "username: %s,UID:%d\n",$1,$3}' passwd 格式输出文件中第一部分的字符串且前面加上username:,第三部分的十进制数且前面加上UID: ,每一行都换行
变量
1.内置变量
②-v 开始执行程序之前都是变量值
FS:输入字段分隔符,默认为空白字符
- awk -v FS=':' '{print $1,FS,$3}' passwd 显示一三部分,中间用空格分隔
OFS:输出字段分隔符,默认为空白字符
- awk -v FS=':' -v OFS=':' '{print $1,$3,$5}' passwd
RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效
- awk -v ORS='**' '{print}' this.txt
NF:字段数量
- awk -F: '{print NF}' /etc/fstab 显示文件以 冒号为分隔符的字段数
NR:行号
- awk '{print NR}' /etc/fstab 打印出行号
FNR:各文件分别计数,行号
- awk '{print FNR}' /etc/fstab /etc/inittab 打印出这两个文件的行号
FILENAME:当前文件名
- awk '{print FILENAME}' /etc/fstab 打印出行数对应的文件名
- awk 'NR==1 {print FILENAME}' /etc/fstab 打印出第一行对应的文件名
ARGC:命令行参数的个数
- awk '{print ARGC}' /etc/fstab
ARGV:数组,保存的是命令行所给定的各参数
- awk 'BEGIN {print ARGV[1]}' /etc/fstab
2.自定义变量
(1)-v var=value
(2)在program中直接定义
awk -v test='hello gawk' '{print test}' /etc/fstab 指定test的值,并输出文件对应的行
awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd 指定sex和age的值,并输出第一部分,和指定的值
3.其他
(1)sort
按数字排序
[root@www test]# sort -n file1
逆序排列
[root@www test]# sort -r file1
安月分排列
[root@www test]# sort -M file1
需要合并两个排过序的文件,而且不需要对合并后的文件再次排序
[root@www test]# sort -m sorted1 sorted2
测试文件是否被排过序
[root@www test]# sort -nC file2
指定主建来排序
[root@www test]# sort -k 4 file1
(2)uniq
uniq命令通过消除重复内容,从而给输入中找出单一的行,也可以找出重复行。uniq只能用于拍过序的数据输入,因此,uniq要么使用管道,要么将排序的文件作为输入。
[root@www test]# cat file11
112
112
134
344
123
134
- 只显示连续唯一的行
[root@www test]# uniq file11
- 不显示连续唯一行
[root@www test]# uniq -u file11
- 显示不重复的唯一行
[root@www test]# sort file11 |uniq -u
- 显示唯一行
[root@www test]# sort file11 |uniq
- 统计各行在文中出现的次数
[root@www test]# sort file11 |uniq -c
- 找出文中的重复行
[root@www test]# sort file11 |uniq -d
- 找出文中的重复行并编号
[root@www test]# sort file11 |uniq -d -c
-s 指定可以跳过前n个字符。 -w 指定用于比较的最大字符数
- 对文件排序,跳过前两个字符去重,留下其中最大字符的
[root@www test]#sort file10 |uniq -s 2 -w 2
(3)comm
交集:打印两个文本所共有的行。
求差:打印指定文件所包含的且不相同的那些行。
差集:打印出包含在文件A 中,但不包含在其他指定文件中的那些行。
[root@www files]# cat file1
applex
orange
gold
silver
steel
iron
[root@www files]# cat file2
orange
gold
cookies
carrot
[root@www files]# sort file1 -o file1;sort file2 -o file2
[root@www files]# comm file1 file2
apple
carrot
cookies
gold
iron
orange
silver
steel
输出的第一列为只有在file1中出现的行,第二列为只有在file2中出现的行,第三列为file1和file2中共有的行。
[root@www files]# comm file1 file2 -1 -2
gold
orange
[root@www files]# comm file1 file2 -1
carrot
cookies
gold
orange
[root@www files]# comm file1 file2 -1 -3
carrot
cookies-1 从输出中删除第1列
-2 从输出中删除第2列
-3 从输出中删除第3列
4、作业
1.1.假设我们有这样一个待处理的文件"grade.txt"
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown -3 12 26 26
L.Tansley 05/99 4712 Brown -2 12 30 28
#打印整个文件
- awk '{print }' grade.txt
#打印第一和第四个域
- awk '{print$1,$4 }' grade.txt
#打印表头
- awk 'BEGIN{print "Name ab cd color 1 2 3\n------------------------------------------------"} {print} ' grade.txt
#下面代码打印第四部分包含 Brown 的行
- awk '$4~/Brown/ {print $0}' grade.txt
#非精确匹配 -- 匹配第三部分含有48的行
- awk '$3~/48/ {print}' grade.txt
#精确匹配--匹配第三部分是48的行
- awk '$3=="48" {print}' grade.txt
#不匹配 使用 ‘!~’----第四部分不包含 Brown 的行
- awk '$4 !~/Brown/ {print}' grade.txt
#小于-- 打印出$6<$7的行后加上Try better at the next comp
- awk '$6< $7 {print $0 "$1 Try better at the next comp"}' grade.txt
#设置大小写
- awk '/[Gg]reen/' grade.txt
#匹配第一个域的第四个字符是‘a’
- awk '$1~ /^...a/' grade.txt
#'或'匹配,使用 ‘|’ ,需使用括号括起来 ---匹配含有Yellow或Brown的行
- # awk '/(Yellow|Brown)/' grade.txt
2.sed和awk有什么区别?
(1)awk:按列(域)操作;sed:按行操作
(2)awk:文本处理语言,适合对文本进行抽取处理;sed:非交互式的编辑器,适合对文本进行编辑
3.awk要处理域的时候,以哪个参数作为分割参数? 答: -F
4.请打印出/etc/passwd 第一个域,并且在第一个域所有的内容前面加上“用户帐号:”
- awk -F: '{print "用户账号:" $1}' passwd
5.请打印出/etc/passwd 第三个域和第四个域
- awk -F: '{print $3,$4}' passwd
6.匹配/etc/passwd 第三域大于100的显示出完整信息
- awk -F: '$3>100{print $0}' passwd
7.请打印第一域,并且打印头部信息为:这个是系统用户,打印尾部信息为:"================"
- awk -F: 'BEGIN{print "这个是系统用户 \n"} {print $1} END{print"========="}' passwd
8.打印行号小于15的,并且最后一域匹配sbin的信息.
- awk -F: '{if ($NR<15 && $NF~/sbin/) print$0}' passwd
9.请打印出第一域匹配daemon的信息.
- cat passwd |zwk -F: '$1=="daemon"' passwd
10.请打印出第三域数字之和
- awk -F: '{sum=sum+$3}END{print sum}' passwd
11.请将/etc/passwd 中的root替换成gongda,记住是临时替换输出屏幕看到效果即可.
- awk -F: 'gsub(/root/,"gongda"){print }' passwd
12.请匹配passwd最后一段域bash结尾的信息,有多少条
- awk -F: '($NF~/bash/){print NR}' /etc/passwd |wc -l
13.请同时匹配passwd文件中,带mail和bash的关键字的信息
- awk -F: '{if($0~/mail/ || $0~/bash/) print $0}' passwd
14.请匹配passwd第三域总大于500的相关信息.
- awk -F: '{if($3>50) print $0}' passwd
15.编写文件fifile的内容如下:
Mike Harrington:[510] 548-1278:250:100:175
Christian Dobbins:[408] 538-2358:155:90:201
Susan Dalsass:[206] 654-6279:250:60:50
Archie McNichol:[206] 548-1348:250:100:175
Jody Savage:[206] 548-1278:15:188:150
Guy Quigley:[916] 343-6410:250:100:175
Dan Savage:[406] 298-7744:450:300:275
Nancy McNeil:[206] 548-1278:250:80:75
John Goldenrod:[916] 348-4278:250:100:175
Chet Main:[510] 548-5258:50:95:135
Tom Savage:[408] 926-3456:250:168:200
Elizabeth Stachelin:[916] 440-1763:175:75:300
Mike 名
Harrington 姓
[510] 548-1278 电话
250:100:175 过去三个月里的捐款
(1))显示所有电话号码
- awk -F: '{print $2}' file
(2)显示Dan的电话号码 # awk -F: '{if($1~/Dan/) print $2}' file
(3)显示Susan的名字和电话号码 # awk -F: '{if($1~/Susan/) print $1,$2}' file
(4)显示所有以D开头的姓 # awk -F '[: ]+' '{if($2~/^D/) print $2}' file
(5))显示所有以一个C或E开头的名 # awk -F '[: ]+' '{if($1~/^[C|E]/) print $1}' file
(6)显示所有只有四个字符的名,这里可以使用length函数,举例: length($1)==10 $1字符为10
# awk -F: '{print $1}' file|awk '{if(length($1)==4) print $1}'
(7)显示所有区号为916的人名 # awk '{print $2}' file |awk -F: '{if($2~/916/) print$1}'
(8)显示Mike的捐款.显示每个值时都有以$开头.如$250$100$175 # awk -F: '{if($1~/Mike/) print "$"$3"$"$4"$"$5}' file
(9)显示姓,其后跟一个逗号和名 # awk -F '[: ]+' '{print $2","$1}' file
16 、统计/etc/fstab 文件中每个文件系统类型出现的次数
17、统计/etc/fstab 文件中每个单词出现的次数
awk '{for(i=0;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' fstab
18 、提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的所有数字
echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk -F "[^[:digit:]]" '{for(k=1;k<=NF;k++) {count[$k]}}END{for(i in count){printf "%s",i}printf "\n"}'
20:统计netstat -tan 中各状态的次数
21:统计出/etc/passwd文件中shell的种类和个数
22:计算/etc/passwd中所有用户的UID平均数,以及GID平均数.
23:使用:符号做分隔符,将字段逆序输出/etc/passwd文件的每行
24:统计ps中VSZ,RSS各自总和
25:根据uid值给用户分等级 Admin system users输出格式: