分类:
2009-11-10 16:06:51
第五章 文本过滤
1.正则表达式
一种用来描述文本模式的特殊语法,由普通字符以及特殊字符(元字符)组成
^ ----只匹配行首
$ ----只匹配行尾
* ----匹配0个或多个此单字符
[] ----只匹配[]内字符,可以使用-表示序列范围[1-5]
\ ----屏蔽一个元字符的特殊含义
. ----匹配任意单字符
pattern\{n\} 只用来匹配前面pattern出现的次数,n为次数
pattern\{n,\}只用来匹配前面pattern出现的次数,至少为n
pattern\{n,m\}只用来匹配前面pattern出现的次数,次数在n-m之间
eg:
A\{3\}B AAAB
A\{3,\}B AAAB AAAAB ...
A\{3,5\}B AAAB AAAAB AAAAAB
2.find命令 ----查找文件和目录
find pathname -options [-print -exec -ok]
pathname --查找的目录路径. .--表示当前目录,/表示根目录
-print 输出
-exec 对匹配的文件执行该参数所给出的shell命令,相应命令形式为'command'{} \;' 注意{}和\;之间的空格
-ok 与-exec相同,不过执行命令前会有提示
options :
-name
-perm
-user
-group
-mtime -n +n (atime,-ctime) 修改时间(访问时间,创建时间)
-size n[c]
-type 查找某一类型的文件
eg.
[test@szbirdora 1]$ find ./ -mtime +5
./helloworld.sh
./nohup.out
查看./目录(当前)下修改时间超过5天的文件
3.grep介绍
grep -c 输出匹配行计数
grep -i 不区分大小写
grep -h 查询多文件时不显示文件名
grep -H 显示文件名
grep -l 查询多文件时只输出包含匹配字符的文件名
grep -n 显示匹配行及行号
grep -s 不显示不存在或不匹配文本的错误信息
grep -v 显示不包含匹配文本的所有行(过滤文本)
eg.
[test@szbirdora 1]$ grep -n 's.a' myfile
2:/dev/sda1 20G 3.3G 16G 18% /
4:/dev/sda2 79G 18G 58G 23% /u01
5:/dev/sda4 28G 3.9G 22G 15% /u02
[test@szbirdora 1]$ grep -n '2$' myfile
5:/dev/sda4 28G 3.9G 22G 15% /u02
grep -options '正则表达式' filename
4.sed介绍
sed不与初始化文件打交道,它操作的只是一个拷贝,然后所有的改动如果没有重定向到一个文件将输出到屏幕
sed是一种重要的文本过滤工具,使用一行命令或使用管道与grep与awk相结合。
sed调用:
1.命令 sed [options] '正则表达式sedcommand' input-files
2.script :sed [options] -f sedscript input-files
sed在文本中查询文本的方式
-行号,可以是简单数字,或一个行号范围
-使用正则表达式
x ----行号
x,y ----行号范围从x到y
x,y! ---不包含行号x到y
sed命令选项:
-n 不打印
-c 下一个命令是编辑命令
-f 如果正在调用sed脚本文件
基本sed命令
p 打印匹配行
= 显示文本行号
a\ 在定位行号后附加新文本信息
i\在定位行号前插入新文本信息
d 删除定位行
c\用新文本替换定位文本
s 使用替换模式替换相应模式
r 从另一个文件中读文本
w 写文本到一个文件
q 第一个模式匹配完成后退去
l 显示与八进制ascii代码等价的控制字符
{}在定位行执行命令组
n 从一个文件中读文本下一行,并附加在下一行
g 将模式2粘贴到/pattern n/
y 传送字符
eg.
[test@szbirdora 1]$ sed -n '2p' myfile
c
打印myfile第2行
[test@szbirdora 1]$ sed -n '2,4p' myfile
c
f
b
打印第二行到第四行
[test@szbirdora 1]$ sed -n '/a/p' myfile
a
打印匹配a的行
[test@szbirdora 1]$ sed -n '2,/2/p' myfile
c
f
b
1
2
打印第二行到匹配'2'的行
awk脚本由模式和动作组成
分隔符、域、记录
注意这里的$1,$2是域与位置变量$1,$2不一样。$0文件中的所有记录
eg:
awk '{print $0}' myfile
awk 'BEGIN {print "IP DATE ----"}{print $1"\t"$4}END{print "end-of -report"}
[test@szbirdora 1]$ df |awk '$1!~"dev"'|grep -v Filesystem
none 1992400 0 1992400 0% /dev/shm
[test@szbirdora 1]$ df |awk '{if ($1=="/dev/sda1") print $0}'
/dev/sda1 20641788 3367972 16225176 18% /
[test@szbirdora shelltest]$ cat employee
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
[test@szbirdora shelltest]$ awk '/[Aa]dams/' employee
Mary Adams 5346 11/4/63 28765
[test@szbirdora shelltest]$ sed -n '/[Aa]dams/p' employee
Mary Adams 5346 11/4/63 28765
[test@szbirdora shelltest]$ grep '[Aa]dams' employee
Mary Adams 5346 11/4/63 28765
三种命令方式下,使用模式匹配查询
[test@szbirdora shelltest]$ awk '{print $1}' employee
Tom
Mary
Sally
Billy
打印文件第一列
[test@szbirdora shelltest]$ awk '/Sally/{print $1"\t"$2}' employee
Sally Chang
打印匹配Sally的行的第一列和第二列
[test@szbirdora shelltest]$ df |awk '$4>20884623'
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda2 82567220 17488436 60884616 23% /u01
/dev/sda4 28494620 4589172 22457992 17% /u02
打印df输出第四列大于××的行
格式输出:
打印函数—
[test@szbirdora shelltest]$ date
Mon Mar 10 15:15:47 CST 2008
[test@szbirdora shelltest]$ date |awk '{print "Month:" $2"\nYear:" $6}'
Month:Mar
Year:2008
[test@szbirdora shelltest]$ awk '/Sally/{print "\t\tHave a nice day,"$1"\t"$2}' employee
Have a nice day,Sally Chang
printf函数
[test@szbirdora shelltest]$ echo "LINUX"|awk '{printf "|%-10s|\n",$1}'
|LINUX |
[test@szbirdora shelltest]$ echo "LINUX"|awk '{printf "|%10s|\n",$1}'
| LINUX|
~匹配符
[test@szbirdora shelltest]$ awk '$1~/Tom/{print $1,$2}' employee
Tom Jones
awk 给表达式赋值
关系运算符:
< 小于
> 大于
== 等于
!= 不等于
>= 大于等于
<= 小于等于
~ 匹配
!~ 不匹配
eg.
[test@szbirdora shelltest]$ cat employee
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
[test@szbirdora shelltest]$ awk '$2~/Adams/' employee
Mary Adams 5346 11/4/63 28765
条件表达式:
condition expression1?expression2:expression3
eg.
awk '{max=($1>$2) ? $1:$2;print max}' filename
运算符
+,-,*,/,%,^,&&,||,!
[test@szbirdora shelltest]$ cat /etc/passwd |awk -F: '\
NF!=7{\
printf("line %d does not have 7 fields:%s\n",NR,$0)}\
$1!~/[A-Za-z0-9]/{printf("line %d,nonalphanumberic user id:%s\n",NR,$0)}\
$2=="*"{printf("line %d,no password:%s\n",NR,$0)}'
awk编程
递增操作符 x++,++x
递减操作符 x--,--x
BEGIN模块
BEGIN模块后面紧跟着动作块,在读入文件前执行。通常被用来改变内建变量的值,如:FS\RS\OFS,初始化变量的值和打印输出标题。
[test@szbirdora shelltest]$ awk 'BEGIN{print "HELLO WORLD"}'
HELLO WORLD
[test@szbirdora shelltest]$ awk 'BEGIN{print "---------LIST---------"}{print}END{print "------END--------"}' donors
---------LIST---------
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
------END--------
重定向和管道
输出重定向
awk输出重定向到一个文件需要使用输出重定向符,输出文件名需要用双引号括起来。
[test@szbirdora shelltest]$ awk -F: '{print $1,$2>"note"}' donors
[test@szbirdora shelltest]$ cat note
Mike Harrington (510) 548-1278
Christian Dobbins (408) 538-2358
Susan Dalsass (206) 654-6279
Archie McNichol (206) 548-1348
Jody Savage (206) 548-1278
Guy Quigley (916) 343-6410
Dan Savage (406) 298-7744
Nancy McNeil (206) 548-1278
John Goldenrod (916) 348-4278
Chet Main (510) 548-5258
Tom Savage (408) 926-3456
Elizabeth Stachelin (916) 440-1763
输入重定向
getline函数
[test@szbirdora shelltest]$ awk 'BEGIN{"date +%Y"|getline d;print d}'
2008
[test@szbirdora shelltest]$ awk -F"[ :]" 'BEGIN{printf "What is your name?";\
getline name<"/dev/tty"}\
$1~ name{print "Found\t" name "\ton line",NR"."}\
END{print "see ya," name "."}' donors
What is your name?Jody
Found Jody on line 5.
see ya,Jody.
[test@szbirdora shelltest]$ awk 'BEGIN{while(getline<"/etc/passwd">0)lc++;print lc}'
36
从文件中输入,如果得到一个记录,getline函数就返回1,如果文件已经到了末尾,则返回0,如果文件名错误则返回-1.
管道:
awk命令打开一个管道后要打开下一个管道需要关闭前一个管道,管道符右边可以使用“”关闭管道。在同一时间只有一个管道存在
[test@szbirdora shelltest]$ awk '{print $1,$2|"sort -r +1 -2 +0 -1"}' names
tony tram
john smith
dan savage
john oldenrod
barbara nguyen
elizabeth lone
susan goldberg
george goldberg
eliza goldberg
alice cheba
|后用""关闭管道
system函数
system("LINUX command")
system("cat" $1)
system("clear")
条件语句
1.if(){}
2.if(){}
else{}
3.if(){}
else if(){}
else if(){}
else{}
[test@szbirdora shelltest]$ awk -F: '{if ($3>250){printf "%-2s%13s\n",$1,"-----------good partman"}else{print $1}}' donors
循环语句
[test@szbirdora shelltest]$ awk -F: '{i=1;while(i<=NF){print NF,$i;i++}}' donors
循环控制语句break、continue
程序控制语句
next从输入文件中读取下一行,然后从头开始执行awk脚本
{if($1~/Peter/){next}
else{print}}
exit 结束awk语句,但不会结束END模块的处理。
数组:
awk '{name[x++]=$1;for(i=0;i
awk内建函数
sub(正则表达式,替换字符[,$n]) ---域n匹配正则表达式的字符串将被替换。
[test@szbirdora shelltest]$ awk '{sub(/Tom/,"Jack",$1);print}' employee
Jack Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
Jack He 3000 8/22/44 320000
index函数 index(字符串,子字符串) 子字符串在字符串中的位置
[test@szbirdora shelltest]$ awk 'BEGIN{a=index("hello","llo");print a}'
3
length函数 length(string) 字符串的长度
[test@szbirdora shelltest]$ awk 'BEGIN{a=length("hello world");print a}'
11
substr函数 substr(字符串,开始位置[,子字符串长度])
[test@szbirdora shelltest]$ awk 'BEGIN{a=substr("hello world",7);print a}'
world
[test@szbirdora shelltest]$ awk 'BEGIN{a=substr("hello world",7,3);print a}'
wor
match(string,正则表达式) 找出字符串中第一个匹配正则表达式的位置,其内建变量RSTART为匹配开始位置,RLENGTH为匹配开始后字符数
[test@szbirdora shelltest]$ awk '{a=match($0,/Jon/);if (a!=0){print NR,a}}' employee
1 5
[test@szbirdora shelltest]$ awk '{a=match($0,/Jon/);if (a!=0){print NR,a,RSTART,RLENGTH}}' employee
1 5 5 3
toupper和tolower函数
[test@szbirdora shelltest]$ awk 'BEGIN{a=toupper("hello");print a}'
HELLO
split函数 split(string,array,fieldseperator)
[test@szbirdora shelltest]$ awk 'BEGIN{"date"|getline d;split(d,date);print date[2]}'
Mar
时间函数
systime() ----1970年1月1日到当前忽略闰年得出的秒数。
strftime(格式描述,时间戳)
[test@szbirdora shelltest]$ awk 'BEGIN{d=strftime("%T",systime());print d}'
13:08:09
[test@szbirdora shelltest]$ awk 'BEGIN{d=strftime("%D",systime());print d}'
03/12/08
[test@szbirdora shelltest]$ awk 'BEGIN{d=strftime("%Y",systime());print d}'
2008
6.sort介绍
sort:
-c 测试文件是否已经排序
-m 合并两个排序文件
-u 删除所有复制行
-o 存储sort结果的输出文件名
-t 域分隔符;用非空格或tab键分割域
+n n为域号,使用此域号开始排序 (注意0是第一列)
-r 逆序排序
n 指定排序是域上的数字排序项
[test@szbirdora 1]$ df -lh|grep -v 'Filesystem'|sort +1
none 2.0G 0 2.0G 0% /dev/shm
/dev/sda1 20G 3.3G 16G 18% /
/dev/sda4 28G 3.9G 22G 15% /u02
/dev/sda2 79G 17G 59G 23% /u01
uniq [option]files 从一个文本文件中去除或禁止重复行
-u 只显示不重复行
-d 只显示有重复数据行,每重复行只显示其中一行
-c 打印每一重复行出现次数
-f n为数字,前n个域被忽略
注意要先排序
7.split cut join 分割和合并文件命令
[test@szbirdora 1]$ split -l 2 myfile split (每两行分割为一个以split名称开头的文件)
[test@szbirdora 1]$ ls
case.sh df.out helloworld.sh iftest.sh myfile nohup.out nullfile.txt parm.sh splitaa splitab splitac splitad splitae
[test@szbirdora 1]$ cat splitaa
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 20G 3.3G 16G 18% /