文本三剑客:grep、sed和awk

grep:文本过滤工具

  • 用途

    文本搜索工具,根据用户指定的“模式”对目标文本逐行进行匹配检查;打印匹配到的行

     功能简单:即搜索匹配文本并予以显示;
     grep:支持REGEXP;
     egrep:或grep -E,支持Extended REGEXP;
     fgrep:不支持REGEXP;
     pattern:由REGEXP或EREGEXP书写的匹配模式
    
  • 使用格式:
    grep 【选项】 pattern file【file2。。。】

     选项:
     	-i:忽略大小写;
     	-o:只显示匹配文本;
     	--color=auto:对匹配文件自动着色
     	-E:使用扩展正则表达式;
     	-v:显示不能匹配的行;
     	-q:不输出内容;
     	-e:模式以-开头时会被grep误识别为选项,该选项确保以-开头的模式
     		被识别为模式;
     	-l:不输出匹配的行,而是输出匹配行的文件名;
     	-A n:追加显示匹配行后的n行内容;
     	-B n:追加显示匹配行前的n行内容;
     	-C n:追加显示匹配行前后各n行内容;
     pattern:由REGEXP或EREGEXP书写
     	REGEXP元字符:
     		1、字符匹配:
     			.:任意单个字符;
     			[]:范围内的任意单个字符;
     			[^]:范围外的任意单个字符;
     			[[:digit:]]:任意数字
     			[[:alpha:]]:任意字母
     			[[:lower:]]:任意小写字母
     			[[:upper:]]:任意大写字母
     			[[:space:]]:空格
     			[[:alnum:]]:任意字母或数字
     			[[:punct:]]:任意标点符号
     			[[:space:]]:空白字符(writespace)
     			[[:blank:]]:空格(space)与定位(tab)字符
     			[[:graph:]]:非空格字符;
     			[[:print:]]:可打印字符;
     			[[:cntrl:]]:控制字符;
     			[[:xdigit:]]:十六进制字符;
     		2、次数匹配
     			\?:一次或0次;
     			\+:至少一次;
     			*:任意次数
     			.*:任意字符
     			\{m,n\}:至少m至多n次;
     			\{,n\}:至多n次;
     			\{m,\}:至少m次;
     			\{m\}:m次;
     		3、位置锚定
     			^:锚定行首;
     			$:锚定行尾;
     			^$:空白行;
     			^pattern$:整行匹配;
     			\<,\b:锚定词首;
     			\>,\b:锚定刺猬
     			\<pattern\>,\bpattern\b:单词匹配
     		4、分组和后向引用
     			\(pattern\):分组
     			\1,\2....:后向引用
     				\1:第一个‘(’及与之匹配的‘)’之间的所有内容,\2同;
     	EREGEXP字符:
     		基本同REGEXP
     		不同点:
     			1、次数匹配不需要使用‘\’;
     			2、分组时不需‘\’,直接使用‘()’;
     			2、支持‘|’符号;
    
  • 使用示例:

     1、	显示/proc/meminfo文件中以大小s开头的行(要求使用两种方式)
     	#grep '^[Ss]' /proc/meminfo
     	#grep '^[s|S]' /proc/meminfo
     2、显示/etc/passwd文件中不以/bin/bash结尾的行
     	#grep -v '\/bin\/bash$' /etc/passwd
     3、显示/etc/passwd文件中ID号最大的用户的用户名
     	#awk -F: 'BEGIN{id=0;user=null};{if($3>=id){id=$3;user=$1}};END{print user}' 
     	 /etc/passwd
     	#sort -t: -k3 -n /etc/passwd |tail -1|grep '^[^:]\+' -o
     	#sort -t: -k3 -n /etc/passwd |sed -n '${/^[^:]\+/p}'|cut -d: -f1
     4、如果用户root存在,显示其默认的shell程序
     	#grep '^root:' /etc/passwd| cut -d: -f7
     5、找出/etc/passwd中的两位或三位数
     	#grep '\b[[:digit:]]\{2,3\}\b' /etc/passwd
     6、显示/etc/rc.d/rc.sysinit文件中,至少以一个空白字符开头的且后面存非空白字符的行
     	#grep '^[[:space:]]\+[^[:space:]]\+' /etc/rc.d/rc.sysinit
     7、找出‘netstat -tan’命令的结果中以‘LISTEN’后跟0,1或多个空白字符结尾的行
     	#netstat -tan|grep 'LISTEN[[:space:]]*$' 
     8、添加用户bash、testbash、basher以及nologin(其shell为/sbin/nologin);而后
     	找出/etc/passwd文件中用户名同shell名的行
     	#for i in bash testbsh basher;do useradd $i;done&&useradd nologin -s 
     	 /sbin/nologin&&grep '^\b\([^:]\+\)\b.*\b\1\b$' /etc/passwd
     	#for i in bash basher testbash;do useradd $i;done&&useradd -r -s /sbin/nologin 
     	 nologin&&awk -F: '{split($7,A,"/");if($1==A[3]){print $0}}' /etc/passwd
     9, /usr目录下的一级目录结构备份:
     	#find /usr/ -maxdepth 1 -type d |sed -e 's;/usr;/test;' -e 's;^;mkdir -pv ;'
     		|bash -s 
    

sed:流编辑器

  • 用途:文本流编辑器、行编辑器

     1、行为最小处理对象;
     2、分:模式空间和保持空间
     3、支持原文件编辑操作(grep、awk不支持)
     4、地址定界支持数字表示(awk不支持);可用$表示末行,但不支持类似vi的$-n,%等表示方法
     5、逐行处理文本,已被读取的行不会再读取,如n动作;
     6、不支持内置变量、函数、条件语句和比较表达式等
     7、用法同grep,着重REGEXP书写的pattern;
    
  • 使用格式:sed 【选项】‘【地址定界】{动作}’ file

     选项:
     	-i:修改原文件;
     	-e:多处编辑;
     	-n:默认打印的模式空间内容不予显示;
     	-f script:指定awk脚本进行文件处理;
     		例:
     			cat > test.sed
     			s/hello/world/g
     			/cool/d
     			/function/a\ hello world
     			^d
     	-r:使用扩展正则表达式;
     地址定界:
     	n:用数字指定某行;
     	m,n:用数字指定某行到某行;
     	/pattern1/,/pattern2/:首次匹配pattern1的行到首次匹配pattern2的行;
     		Tip:经测试,这里的首次不指仅一次匹配;全文有多处内容符合条件会全部打印出;
     	m,/pattern/;/pattern/,n:行号和pattern混用
     	$:表示末行;
     	$!;n!;/pattern/!:行取反,除开匹配的行对剩下的行进行处理;
     	地址定界省略:表示对全文进行处理;
     	m~n:由m行开始每次步进n行进行处理,1~2处理奇数行,2~2处理偶数行;
     动作:
     	p:打印模式空间内容;
     		例1:#sed -n ‘1p’ file:打印文件第一行内容;
     	P:打印模式空间第一行内容;
     		例2:#sed -n ‘2{N;P}’ file:打印文件第二行内容;
     	d:删除模式空间内容;停止后续动作,重新执行sed命令;
     		例3:#sed -n ‘1,10d;p’ file:文件的前10行内容不予显示
     	D:删除模式空间第一行内容;停止后续动作,对剩下内容重新执行sed命令;
     		例4:#sed  'N;$!D' file:显示文件最后2行内容
     	a\ string:在匹配行下面追加文本;
     		例5:#sed ‘/^root/a\HELLO KITTY’ file:在文件中以root开头的行下面添加HELLO KITTY字符串
     	i\ string:在匹配行上面追加文本;
     		例6:#sed ‘3,/\bshu\b/i\ COMMON USER’ file:在文件第3行到第一次匹配到单词shu的行
     			前面添加COMMON USER字符串;
     	c\ string:用string替换匹配行;
     		例7:#sed '/^\broot\b/,/^\bshu\b/c\******* file:把文件中第一个以root单词开头的行到第
     			一个以书单词开头的行之间的行内容替换为********;
     		Tip:实测多行匹配的内容被替换为单行‘********’
     	h:模式空间内容覆写到保持空间;
     		例8:#sed -n '1!G;h;$p' file:倒序显示文件
     	H:模式空间内容追加到保持空间;
     		例9:#sed 'H;$g' file:显示文件两遍;
     	g:保持空间内容覆写到模式空间;
     		例10:#sed ‘g’ file:文件内容显示为空
     	G:保持空间内容追加到模式空间;
     		例11:#sed ‘G’ file:文件内容每行之间以空白行隔开显示;
     	x:模式空间和保持空间内容互换;
     		例12:#sed ‘1h;$x’ file:把最后一行的内容显示为第一行的内容
     	r file:读取指定文件到匹配行下面;
     		例13:#sed ‘$r /tmp/test’ file:把/tmp/test文件的内容追加到file文件的末尾
     	w file:把匹配行写入到文件中;
     		例14:#sed ‘10,$w /tmp/test’ file:把文件第10行到最后一行的内容写入到/tmp/test文件中
     	q:退出sed进程;
     		例15:#sed ‘5q’ file:显示文件前5行
     	s:查找替换;‘g’全局替换
     		例16:#sed ‘s/\bshu\b/yang/’ file:把文件行中首个单词shu替换成yang;
     		例17:#sed ‘s/\bshu\b/yang/g’ file:把文件中所有单词shu替换成yang;
     		g如果替换成数字的话,表示匹配到的第几个字段要进行替换;
     	n:读取匹配行的下一行到模式空间,并用下一个动作处理;
     		例18:#sed -n ‘n;p’ file:显示偶数行;
     		例19:#sed ‘n;d’ file:显示奇数行;
     	N:追加匹配行的下一行到模式空间,并生成新行号;
     		例20:#sed ‘N;$!D’ file:显示文件最后两行
     	=:打印行号(行号单独一行;)
     		例20:#sed ‘=’ file:在每一行上方打印行号
     pattern:
     	sed支持REGEXP和EREGEXP的格式;且
     	&:引用前面pattern匹配的所有内容
     		例21:sed ‘s/^\broot\b/&er/g’ file:替换文件中所有以单词root开头的行的root单词为rooter;
    

awk:报告生成器

  • 用途:文本报告生成器。

     1、用于生成格式化的文本报告,不支持原文件标记操作;
     2、支持内建变量、函数,自定义变量、函数,比较表达式、组合语句、控制语句、脚本等复杂功能
     3、以行中的段为最小操作对象;
     4、使用注意:
     	a、字符串要用“”双引号引起,否则会造成语法错误
    
  • 使用格式:awk 【选项】 ‘【地址定界】{动作;动作;。。。}’ file

     选项:
     	-F :指定字段分隔符,可以指定多个,在进行第一个分隔符切割后使用
     		第二个分隔符对分割后的字段再次切割;
     	-v var=value:自定义变量;
     	-f script-file:从文件中读取awk命令;
     地址定界:
     	1、不指定:匹配所有行;
     		例1:#awk -F: '{print $1}' /etc/passwd:显示系统中的所有用户名;
     	2、/pattern/:被模式匹配的行;
     		例2:#awk -F: '/^\<root\>/{print $1,$3}' /etc/passwd:显示root用户的用户名和ID;
     		Tip:
     			/pattern/的格式中//是必须的;
     			经测试指定词首尾不能用\b;
     	3、关系表达式:为真(结果为非0值、非空字符串)时被匹配;
     		例3:#awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
     			显示shell为/bin/bash的用户和对应shell;
     		例4:#awk 'NR>3&&NR<10{print $0}' passwd1
     			组合关系表达式显示4到9行的内容
     		例5:#awk -F: '$1=="shu"||$1=="sshd"{print $1,$3}' /etc/passwd
     			显示shu或sshd用户的用户名和id号;
     	4、行范围:/parttern1/,/pattern2/,不支持数字格式
     		例6:#awk '/^\<bin\>/,/^\<shu\>/{print $0}' /etc/passwd:显示/etc/passwd文件中bin用户
     			和shu用户之间的所有内容;
     		Tip:$不能和pattern混合使用($可用吗???)
     	5、BEGIN和END:在文本处理之前或之后执行一次;
     		例7:#awk 'BEGIN{printf "%30s\n","hello world"};{print $0}' /etc/passwd
     			在文件开头打印“hello world”字符串,随后打印文件内容
     		例8:#netstat -tan |awk '(NR>2){let ips[$NF]++};END{for(i in ips){print i":",ips[i]}}'
     			统计tcp连接各状态连接数;
     		Tip:使用时注意格式
     			awk 'BEGIN{action};【地址定界】{action};END{action}’ file
     动作:多个动作之间用‘;’号隔开,可由以下语句组成:
     	1、expression,赋值、比较等表达式
     		例9:#awk ‘BEGIN{str=“hello world”;print str}’
     		例10:#awk -F: '{if(NR<5){print $1,$3}}' /etc/passwd
     	2、控制语句:if、while、for、do等
     		if语句:if(conditons){actions}
     			例11:#awk -F: '{if($1~/root/){print $1,$3}}' /etc/passwd,单分支if语句;
     			例12: #awk -F: '{if($3>0&&$3<500){print "system user:",$1}else{print "common 
     				user:",$1}}' /etc/passwd,双分支if语句
     		for语句:for(expr1;expr2;expr3){action}
     			例13: #awk 'BEGIN{for(i=1;i<10;i++){m+=i};print m}'
     			for特殊用法:for(var in array){action},遍历数组中的元素;
     				例14:awk '{ips[$1]++};END{for(i in ips){print i":",ips[i]}}' 
     					/var/log/httpd/access_log,web服务器ip访问统计;
     		wile语句:while(conditoons){actions}
     			一般对一行内的多个字段进行类似处理时使用;
     			例15:#awk -F: '{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/passwd
     				显示文件中每个字段的内容和长度
     		do语句:do{actions}while(conditions)
     			和while语句的区别是actions在前,所以即使conditions不满足,也至少执行一次actions
     			例16:#awk -F: '{i=7;do{print $i,length($i);i++}while(i<NF)}' /etc/passwd
     				passwd文件中只有7个字段,条件i<NF即7<7不满足,但依然执行了一次打印命令;
     		switch语句:略
     		break和continue:退出循环或退出本次循环;用于for或while、switch语句中
     			例17:#awk -F: '{i=1;while(i<=NF){if($i=="root")break;print $i,length($i);i++}}' passwd
     				遍历文件中字段,root字段到行尾的内容不予显示,打印字段名和字段长度;
     			例18:#awk -F: '{i=1;while(i<=NF){if($i=="root"){i++;continue};print 
     				$i,length($i);i++}}' passwd:不显示root字段内容和长度的显示;
     		next语句:提前结束对本行的处理而进入下一行
     			例19:#awk -F: '{if($3%2==0)next;print $1,$3}' /etc/passwd
     				显示uid有奇数的用户名和uid;
     		delete array【index】:删除数组元素;
     		delete array:删除数组;
     		exit:退出awk命令
     			#awk -F: '{if($1=="shu")exit;print $1,$3}' /etc/passwd
     awk中的数组	、函数、变量:
     	数组:只支持关联数组;
     		关联数组:array【index】
     			1、同bash中数组用法相似,但功能较为简单
     			2、数组元素值value要使用双引号(bash数组可以不用,awk中字符串必要使用双引号,
     				否则语法错误),在定义数组元素时,下标最好也使用双引号。
     			3、遍历数组用for(var in array){actions};
     			4、判断元素在数组中是否存在:index in array
     			例19.1:awk 'BEGIN{weekdays["a"]="monday";weekdays["b"]="tuesday";if("a" in weekdays){print "ok"}}'
    
     		例20:统计tcp状态数据
     			 #netstat -tan|awk '(NR>2){stat[$NF]++};END{for(i in stat){print i":"stat[i]}}'
     		例21:统计web访问ip
     			 #awk '{ips[$1]++};END{for(i in ips){print i":"ips[i]}}' /var/log/httpd/access_log
     	函数:内置函数和自定义函数
     		内置函数:http://www.runoob.com/w3cnote/awk-built-in-functions.html
     		常用:
     			sub(a,b,c):字符串替换。将c中的字符串a(或pattern)替换成字符串b(可省,默认为$0);
     				例22:#awk 'BEGIN{info="hello world";sub("world","word",info);print info}'
     			gsub(a,b,c):同上,全局替换,c中出现的每个符合条件a的字符串替换成b;
     				例23:#awk 'BEGIN{info="hello haha world";gsub(/\<h[[:alpha:]]*\>/,"go",
     					info);print info}'
     			substr(a,b,c):字符串取子串。在字符串a中从b(数值)处往后截取共c个字符长度的字符串;c省略时到字符串尾部
     				例24:#awk 'BEGIN{info="abcdefghijk";print substr(info,7,2)}'
     			length(a):计算字符串a的长度。
     				例25:#awk 'BEGIN{info="abcdefg";print length(info)}'
     			index(a,b):计算字符串b在a中的位置,不存在时返回0;
     				例26:#awk 'BEGIN{info="abcdefg";print index(info,"de"),index(info,"h")}'		
     			split(a,b,c):以c为分隔符分割字符串a,并将字段依序存入数组b中
     				例27:#awk 'BEGIN{info="/etc/rc.d/rc0.d/init";split(info,str,"/");for(i in str){print i,str[i]}}'
     			toupper(a):将字符串a中的字母转换为大写;
     				例28:awk 'BEGIN{info="abcde";print toupper(info)}'
     			tolower(a):将字符串a中的字母转换为小写;
     				例29:awk '{print tolower($0)}' file:将文件的内容小写显示
     		自定义函数:http://www.runoob.com/w3cnote/awk-user-defined-functions.html	
     	变量:	内置变量和自定义变量
     		内置变量:http://www.runoob.com/linux/linux-comm-awk.html
     			常用:
     				NR:number of record,行号;
     				NF:number of field,字段号;
     				FS:field separator,输入字段分隔符;默认空格
     				OFS:out field separator,输出字段分隔符;默认空格
     				$0:当前记录
     				$1,$2,$3。。。:字段1、2、3。。。
     				FILENAME:当前文件名
     			例30:默认记录分隔符为换行符,使用空白行为记录分隔符
     				# ake -v RS=‘’
     		自定义变量:
     			1、在选项-v中定义;-v var=value;
     			2、在action中定义;var=value;
     awk脚本文件:
     	awk -f script file:依照脚本文件script中的awk指令对文件file进行处理:
     	script文件语法示例:
     		$ cat cal.awk
     			#!/bin/awk -f
     			#运行前
     			BEGIN {
     			math = 0
     			english = 0
     			computer = 0
    
     			printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
     			printf "---------------------------------------------\n"
     			}
     			#运行中
     			{
     			math+=$3
     			english+=$4
     			computer+=$5
     			printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
     			}
     			#运行后
     			END {
     			printf "---------------------------------------------\n"
     			printf "  TOTAL:%10d %8d %8d \n", math, english, computer
     			 printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
     			}
    

练习题:

1、删除/boot/grub/grub.conf文件中所有以空白开头的行行首的空白字符;
2、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符;
3、echo一个绝对路径给sed命令,取出其基名;取出其目录名;
4、显示文件最后两行;
5、显示文件最后一行;
6、显示文件最后一行;	
7、文件每一行都增加一个空白行显示;
8、文件中的空白行删除后在每一行增加一个空白行显示;
9、显示奇数行;
10、逆向显示文件
11、复制/etc/rc.d/rc.sysinit文件至/tmp目录,将/tmp/rc.sysinit文件中的以至少一个空白字符开头的行的行首加#
12、复制/boot/grub/grub.conf至/tmp目录中,删除/tmp/grub.conf文件中的行首的空白字符
13、删除/tmp/rc.sysinit文件中的以#开头,且后面跟了至少一个空白字符的行的#和空白字符
14、为/tmp/grub.conf文件中前三行的行首加#号
15、将/etc/yum.repos.d/CentOS-Media.repo文件中所有的enabled=0或gpgcheck=0的最后的0修改为1
16、每4小时执行一次对/etc目录的备份,备份至/backup目录中,保存的目录名为形如etc-201504020202
17、每周2,4,6备份/var/log/messages文件至/backup/messages_logs/目录中,保存的文件名形如
	messages-20150402
18、每天每两小时取当前系统/proc/meminfo文件中的所有以S开头的信息至/stats/memory.txt文件中
19、工作日的工作时间内,每两小时执行一次echo“howdy”
20、创建目录/tmp./testdir-当前日期时间
21、在此目录创建100个空文件:file1-file100。
22、显示/etc/passwd文件中位于第偶数行的用户的用户名。
23、删除文件最后两行。

学习记录:

1、sed  ‘$N;$!D’  test;
   sed ‘$!N;$!D’ test;
   sed;sed ‘N;$!D’ test
   sed  -n ‘N;$p’的理解
	解:sed -n ‘$N;$!D’ test: 显示test最后一行
			$N表示对最后一行执行追加操作(无意义);
			$!D表示不对最后一行执行删除操作,其他行都执行删除操作;
			输出结果显示文件最后一行;
			Tip:$N无意义,整个命令等同于sed  ‘$!d’ test;
		sed  ‘$!N;$!D’ test:显示test最后两行
			$!N表示对最后一行之外的行执行追加操作;
			$!D表示对最后一行之外的行执行删除模式空间第一行操作,并对剩下内容重新执行sed命令;
			输出结果显示文件最后两行;
			猜测:倒数第二行时N执行追加动作,并修改行号,成为末行,D动作检测到行号为末行,
				不执行动作;
		sed ‘N;$!D’ test
			N表示对所有处理行进行追加操作;
			$!D表示对最末行之外的行执行删除模式空间第一行操作,并对剩下内容重新执行sed命令;
			输出结果显示文件最后两行;
		sed -n ‘N;$p’ test  ???
			按预想是要显示最后两行,结果test为奇数行时显示无输出结果,偶数行时为最后两行
2、sed -f file中file文件的格式?awk -f file中文件的格式?
3、关于awk中数组的问题?
	 awk 'BEGIN{num[0]="1";num[1]="2";num[2]="3";for(i in num){print i}}'中如果使用a,b,c
	 作为数组下标,则输出结果为空,为什么?不支持字母下标?
   解:数组元素在定义时,下标要用“”双引号引起,即
   	awk 'BEGIN{num["a"]="1";num["b"]="2";num["c"]="3";for(i in num){print i,num[i]}}'
   析:在定义数组元素时,下标没有使用双引号也可能成功,但最好使用双引号来避免错误。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值