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]}}'
析:在定义数组元素时,下标没有使用双引号也可能成功,但最好使用双引号来避免错误。