引言&&grep
以前我们用grep在一个文件中找出包含某些字符串的行,比如在头文件中找出一个宏定义。其实grep还可以找出符合某个模式(Pattern)的子类字符串。例如找出所有符合xxxxx@xxxx.xxx模式的字符串(也就是email地址),要求x字符可以是字母、数字、下划线、和数点或减号,email地址的每一部分可以有一个或多个x字符,例如abc.d@ef.com、1_2@987-6.54,当然符合这个模式的不全是合法的email地址,但至少可以做一次初步筛选,筛掉a.b、c@d等肯定不是email地址的字符串。再比如,找出所有符合yyy.yyy.yyy.yyy模式的字符串(也就是IP地址),要求y是0-9的数字,IP地址的每一部分可以有1-3个y字符。
规定某些特殊语法表示字符类、数量限定符和位置关系,然后用这些特殊语法和普通字符一起表示一个模式,这就是正则表达式(Regular Expression)。例如email地址正则表达式可以写成[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+,IP地址的正则表达式可以写成[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}。我们先看看正则表达式在grep中怎么用。
例如有这样一个文本文件testfile:
192.168.1.1
1234.234.04.5678
123.4234.045.678
abcde
$ egrep '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' testfile
192.168.1.1
1234.234.04.5678
egrep相当于grep -E,表示采用Extended正则表达式语法。grep的正则表达式 有Basic和Extended两种规范,另外还有fgrep命令,相当于grep - F,表示只搜索固定字符串不搜索正则表达式模式,不会按正则表达式的语法解释后面的参数。192.168.1.1符合上述模式,由三个.隔开的四段组成,每段都是1到3个数字,所以这一行被找出来了,可为什么1234.234.04.5678也被找出来了呢?因为grep找的是包含某个模式的行,这行不包含一个符合模式的字符串234.234.04.567。相反,123.4234.045.678这一行不包含符合模式的字符串,所以不会被找出来。
grep是一种查找过滤工具,正则表达式在grep中用来查找符合模式的字符串。其实正则表达式还有一个重要的应用是验证用户输入是否合法,例如用户通过网页表单提交自己的email地址,就需要用程序验证一下是不是合法的email地址。
字符类(Character Class):如上例的x和y,它们在模式中表⽰⼀个字符,但是取值范围是⼀类字符中的任意⼀个。
数量限定符(Quantifier): 邮件地址的每⼀部分可以有⼀个或多个x字符,IP地址的每⼀部可以有1-3个y字符
位置限定符(Anchor):描述各种字符类以及普通字符之间的位置关系,例如邮件地址分三部分,⽤普通字符@和.隔 开,IP地址分四部分,用.隔开,每⼀部分都可以用字符类和数量限定符描述。
注意:
1.注意正则表达式参数用单引号括起来了,因为正则表达式中用到的很多特殊字符在Shell中
也有特殊含义(例如\),只有用单引号括起来才能保证这些字符原封不动地传给grep命令,而不会被Shell解释掉。
2.再次注意grep找的是包含某⼀模式的行,而不是完全匹配某⼀模式的行。查找a*这个模式的结果是三行都被找出来了a*匹配0个或多个a,而第三行包含0个a,所以也包含了这一模式。单独⽤用a*这样的正则表达式做查找没什么意义,一般是把a*作为正则表达式的一部分来用。
3.位置限定符可以帮助grep更准确地查找,
4.以上介绍的是grep正则表达式的Extended规范,Basic规范也有这些语法,只是字符?+{}|()应解释 为普通字符,要表⽰上述特殊含义则需要加\转义。如果⽤用grep而不是egrep,并且不加-E参数,则应该遵照Basic 规范来写正则表达式一定要注意!!!!!)
sed基本概念
sed为流编译器,就是把前一个程序输入引入sed的输出,经过一系列编辑命令转换成另一种格式输出,在shell脚本和makefile中作为过滤器使用非常普遍。
sed处理的⽂件既可以由标准输⼊重定向得到,也可以当命令⾏参数传⼊,命令⾏参数可以一次传⼊多个⽂件,sed会依次处理。sed的编辑命令可以直接当命令⾏参数传⼊,也可以写成⼀个脚本⽂件然后⽤-f参数指定,编辑命令的格式为
/pattern/action其中pattern是正则表达式,action是编辑操作。sed程序⼀⾏⼀行读出待处理⽂文件,如果某⼀⾏与pattern匹配,则执⾏相应的action,如果一条命令没有pattern⽽只有action,这个action将作⽤于待处理⽂件的每一⾏。sed是⼀种在线编辑器,它⼀次处理⼀⾏内容。处理时,把当前处理的⾏存储在临时缓冲
区中,称为“模式空间”(pattern space),接着⽤sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一⾏,这样不断重复,直到⽂件末尾。⽂件内容并没有改变,除⾮你使⽤重定向存储输出。Sed主要⽤来⾃自动编辑⼀个或多个⽂件;简化对⽂件的反复操作;sed默认安照Basic 规范基本匹配!
1./pattern/p :打印匹配pattern的行
使用p命令需要注意sed是把待处理文件的内容连通处理结果一起输入到标准输出的,所以p除了打印文件内容还额外打印一遍匹配正则表达式的行,但是如果只想输出处理结果加上-n,这种用法相当于grep命令
2./pattern/d :删除匹配正则表达式的行,但是请注意sed命令不会修改原文件,删除命令只表示某些行不打印出来,而不是从原文件中删除。
3./pattern/s/pattern1/pattern2/:查找符合pattern的行,将该行第一个匹配pattern1的字符串替换为pattern2
4. /pattern/s/pattern1/pattern2/g:查找符合pattern的⾏,将该⾏所有匹配
pattern1的字符串替换为pattern2
5.sed -i : 做的操作会修改原⽂件
6.定址:定址⽤于决定对哪些⾏进⾏编辑。地址的形式可以是数字、正则表达式、或⼆者的结合。如果没有指定地址,sed将处理输⼊⽂件的所有⾏。
sed -n ‘3p’ file #打印第三⾏
sed -n ‘100,300p’ file #打印100〜300⾏的信息(包括100和300)地址是逗号分隔的,那么需要处理的地址是这两行之间的范围(包括这两行在内)。范
围可以⽤数字、正则表达式、或⼆者的组合表⽰。
sed ‘2,5d’ file #删除第⼆⾏到第五⾏
sed ‘/start/ ,/end/d’ file #删除包含’start’⾏和’end’⾏之间的⾏
sed ‘/start/, 10d’ file #删除包含’start’ 的⾏到第⼗⾏的内容
7. 命令和选项
sed命令告诉sed如何处理由地址指定的各输⼊⾏,如果没有指定地址则处理所有的输⼊⾏。
命令
a\ :在当前⾏后添加⼀⾏或多⾏。多⾏时除最后⼀⾏外,每⾏末尾需⽤“\”续⾏
c\ :⽤此符号后的新⽂本替换当前⾏中的⽂本。多⾏时除最后⼀⾏外,每⾏末尾需⽤用”\"续⾏
i\ :在当前⾏之前插⼊⽂本。多⾏时除最后⼀⾏外,每⾏末尾需⽤”\"续⾏d删除⾏
h : 把模式空间⾥的内容复制到暂存缓冲区
H :把模式空间⾥的内容追加到暂存缓冲区
g :把暂存缓冲区⾥的内容复制到模式空间,覆盖原有的内容
G:把暂存缓冲区的内容追加到模式空间⾥,追加在原有内容的后⾯
l :列出⾮打印字符
p :打印⾏
q :结束或退出sed
r :从⽂件中读取输⼊⾏
! : 对所选⾏以外的所有⾏应⽤命令
s :⽤用⼀个字符串替换另⼀个
g :在⾏内进⾏全局替换
w :将所选的⾏写⼊⽂件
x :交换暂存缓冲区与模式空间的内容
y :将字符替换为另⼀字符(不能对正则表达式使⽤y命令)选项
-e :进⾏多项编辑,即对输⼊⾏应⽤多条sed命令时使⽤
-n :取消默认的输出
-f :指定sed脚本的⽂文件名
8. 退出状态
sed不向grep⼀样,不管是否找到指定的模式,它的退出状态都是0。只有当命令存在语法错误时,sed的退出状态才不是0。
正则表达式:与grep⼀样,sed也⽀持殊元字符,来进行模式查找、替换。不同的是,sed使⽤的正则表达式是括在斜杠线"/"之间的模式。如果要把正则表达式分隔符"/"改为另⼀个字符,⽐如o,只要在这个字符前加⼀个反斜线,在字符后跟上正则表达式,再跟上这个字符即可。例如:sed -n '\o^Myop' datafile
^:⾏⾸定位符:/^my/ 匹配所有以my开头的⾏
$:⾏尾定位符:/my$/ 匹配所有以my结尾的⾏
.:匹配除换⾏符以外的单个字符: /m..y/ 匹配包含字⺟m,后跟两个任意字符,再跟字母y的⾏
*:匹配零个或多个前导字符:/test*/ 匹配包含string tes,后跟零个或多个t字⺟的⾏
[]:匹配指定字符组内的任⼀字符 :/t[eE]st/ 匹配包含test或tEst的⾏
[^]:匹配不在指定字符组内的任⼀字符:/t[^eE]st/ 匹配string 以t开头,但st之前的那个字符不是e或E的⾏
\(..\):保存已匹配的字符: 标记元字符之间的模式,并将其保存为标签1,之后可以使⽤\1来引⽤它。最多可以定义9个标签,从左边开始编号,最左边的是第⼀个。此例中,对第1到第3⾏进行处理,tes被保存为标签1,如果发现tes,则替换为testttt。
&:保存查找串以便在替换串中引⽤:s/test/*&*/g 符号&代表查找串。test将被替换为*test*
\<:词⾸首定位符:/\<my/ 匹配包含以my开头的单词的⾏
\>:词尾定位符:/my\>/ 匹配包含以my结尾的单词的⾏
x\{m\}:连续m个x:/9\{5\}/ 匹配包含连续5个9的⾏
x\{m,\}:⾄少m个x:/9\{5,\}/ 匹配包含⾄少连续5个9的⾏
x\{m,n\}:⾄至少m个,但不超过n个x:/9\{5,7\}/ 匹配包含连续5到7个9的⾏
模式空间保持空间
sed在正常情况下,将处理的⾏读⼊模式空间(pattern space),脚本中的“sed-command(sed命令)”就⼀条接着⼀条进⾏处理,直到脚本执⾏完毕。然后该⾏被输出,模式(pattern space)被清空;接着,在重复执⾏刚才的动作,⽂件中的新的⼀⾏被读⼊,直到⽂件处理完毕。⼀般情况下,数据的处理只使⽤模式空间(pattern space),按照如上的逻辑即可完成主要任务。但是某些时候,使⽤通过使⽤保持空间(hold space),还可以带来意想不到的效果。
模式空间:可以想成⼯程⾥⾯的流⽔水线,数据直接在它上⾯进⾏处理。
保持空间:可以想象成仓库,我们在进⾏数据处理的时候,作为数据的暂存区域。
正常情况下,如果不显⽰使⽤某些⾼级命令,保持空间不会使⽤到!
sed命令:
+ g:[address[,address]]g 将hold space中的内容拷⻉到pattern space中,原来pattern space⾥的内容清除
+ G:[address[,address]]G 将hold space中的内容append到patternspace\n后
+ h:[address[,address]]h 将pattern space中的内容拷⻉到hold space中,原来的hold space⾥的内容被清除
+ H:[address[,address]]H 将pattern space中的内容append到holdspace\n后
+ d:[address[,address]]d 删除pattern中的所有⾏,并读⼊下⼀新⾏到pattern中
+ D:[address[,address]]D 删除multiline pattern中的第⼀⾏,不读⼊下⼀⾏
+ x:交换保持空间和模式空间的内容
awk基本使用
sed以⾏为单位处理⽂件,awk⽐sed强的地⽅在于不仅能以⾏为单位还能以列为单位处理⽂件。awk缺省的⾏分隔符是换⾏,缺省的列分隔符是连续的空格和Tab,但是⾏分隔符和列分隔符都 可以⾃定义,⽐如/etc/passwd⽂件的每⼀⾏有若⼲个字段,字段之间以:分隔,就可以重新定义awk的列分隔符为:并以列为单位处理这个⽂件。awk实际上是⼀门很复杂的脚本语⾔,还有像C语⾔⼀样的分⽀支和循环结构,但是基本⽤法和sed类似。和sed⼀样,awk处理的⽂件既可以由标准输⼊重定向得到,也可以当命令⾏参数传⼊,编辑命令可以直接当命令⾏参数传⼊,也可以⽤-f参数指定⼀个脚本⽂件。和sed类似,pattern是正则表达式,actions是⼀系列操作。awk程序⼀⾏⼀⾏读出待处理⽂件,如果某⼀⾏与pattern匹配,或者满⾜condition条件,则执⾏相应的actions,如果⼀条awk命令只有actions部分,则actions作⽤于待处理⽂件的每⼀⾏。
awk的调用方式
1.命令⾏⽅式
awk [-F field-separator] 'commands' input-file(s)其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的⽂件。在awk中,⽂件的每⼀⾏中,由域分隔符分开的每⼀项称为⼀个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
2.shell脚本方式
将所有的awk命令插⼊⼀个⽂件,并使awk程序可执⾏,然后awk命令解释器作为脚本的⾸⾏,⼀遍通过键⼊脚本名称来调⽤。相当于shell脚本⾸⾏的:#!/bin/sh可以换成:#!/bin/awk -f
3.将所有的awk命令插⼊⼀个单独⽂件,然后调⽤:awk -f awk-script-file input-file(s)其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上⾯的是⼀样的。
awk调用正则表达式的方法
A.awk语句:
awk ‘/REG/{action}’/REG/为正则表达式,可以将$0中,满⾜条件记录送⼊到:action进⾏处理
B. awk正则运算语句(〜~,〜~!等同!〜~)
C. awk内置使⽤用正则表达式函数
gsub( Ere, Repl, [ In ] )
sub( Ere, Repl, [ In ] )
match( String, Ere )
split( String, A, [Ere] )
BEGIN和END
awk工作流程是这样的:先执⾏BEGIN,然后读取⽂件,读⼊有\n换⾏符分割的⼀条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表⽰所有域,$1表⽰第⼀个域,$n表⽰第n个域,随后开始执⾏模式所对应的动作action。接着开始读⼊第⼆条记录·····直到所有的记录都读完,最后执⾏END操作。
awk内置变量
ARGC 命令⾏参数个数
ENVIRON ⽀持队列中系统环境变量的使⽤
FILENAME awk浏览的⽂件名
FNR 浏览⽂件的记录数
FS 设置输⼊域分隔符,等价于命令⾏ -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
print和printf
awk中同时提供了print和printf两种打印输出的函数。其中print函数的参数可以是变量、数值或者字符串。字符串必须⽤双引号引⽤,参数⽤逗号分隔。如果没有逗号,参数就串联在⼀起⽽⽆法区分。这⾥,逗号的作⽤与输出⽂件的
分隔符的作⽤是⼀样的,只是后者是空格⽽已。printf函数,其⽤法和c语⾔中printf基本相似,可以格式化字符串,输出复杂时,printf更加好⽤,代码更易懂。
awl数组
因为awk中数组的下标可以是数字和字⺟,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的⼀张针对key/value应⽤hash的表格⾥。由于hash不是顺序存储,因此在显⽰数组内容时会发现,它们并不是按照你预料的顺序显⽰出来的。数组和变量⼀样,都是在使⽤时⾃动创建的,awk也同样会⾃动判断其存储的是数字还是字符串。⼀般⽽⾔,awk中的数组⽤来从记录中收集信息,可以⽤于计算总和、统计单词以及跟踪模板被匹配的次数等。
CUT
定义:正如其名,cut的⼯作就是“剪”,具体的说就是在⽂件中负责剪切数据⽤的。cut是以每⼀行为⼀个处理对象的,这种机制和sed是⼀样的。
cut命令主要是接受三个定位⽅法:
第⼀,字节(bytes),⽤选项-b
第⼆,字符(characters),⽤选项-c字符cut相对⽐比较简单,中⽂字符和空格都算⼀个字符。
第三,域(fields),⽤选项-f-d指定域分隔符,-f 指定要剪出哪⼏个域,这个与awk的输出特定字段功能⼀样。
Sort
1. sort将⽂件的每⼀⾏作为⼀个单位,相互⽐较,⽐较原则是从⾸字符向后,依次按ASCII码值进⾏⽐较,最后将他们按升序输出。
2. sort的-u选项它的作⽤很简单,就是在输出⾏中去除重复⾏
3. sort的-r选项sort默认的排序⽅式是升序,如果想改成降序,就加个-r就搞定了。
4. sort的-o选项由于sort默认是把结果输出到标准输出,所以需要⽤重定向才能将结果写⼊⽂件,形如sortfilename > newfile。但是,如果你想把排序结果输出到原⽂件中,⽤重定向可就不⾏了
5. sort的-n选项你有没有遇到过10⽐2⼩的情况。我反正遇到过。出现这种情况是由于排序程序将这些数字按字符来排序了,排序程序会先⽐较1和2,显然1⼩,所以就将10放在2前⾯喽。这也是sort的⼀贯作风。我们如果想改变这种现状,就要使⽤用-n选项,来告诉sort,“要以数值来排序”!
6. sort的-t选项和-k选项 sort提供了-t选项,后⾯可以设定间隔符。 指定了间隔符之后,就可以⽤用-k来指定列数了
7. 其他的sort常⽤选项-
f会将⼩写字母都转换为⼤写字母来进行比较,亦即忽略⼤⼩写
-c会检查⽂件是否已排好序,如果乱序,则输出第⼀个乱序的⾏的相关信息,最后返回1
-C会检查⽂件是否已排好序,如果乱序,不输出内容,仅返回1
-M会以⽉份来排序,⽐如JAN⼩于FEB等
-b会忽略每⼀⾏前⾯的所有空⽩部分,从第⼀个可见字符开始⽐较。
Unip
说明:这个命令读取输⼊⽂件,并⽐较相邻的⾏行。在正常情况下,第⼆个及以后更多个重复⾏将被删去,⾏⽐较是根据所⽤字符集的排序列进⾏的。该命令加⼯后的结果写到输出⽂件中。输⼊⽂件和输出⽂件必须不同。如果输⼊⽂件⽤“- ”表⽰,则从标准输⼊读取。
该命令各选项含义如下:、
– c 显⽰输出中,在每⾏⾸加上本⾏在⽂件中出现的次数。它可取代- u和- d
选项。
– d 只显⽰重复⾏。
– u 只显⽰⽂件中不重复的各⾏。