发信人: suit (伊默), 信区: Unix_Linux
标 题: Linux命令中正则表达式的运用
发信站: 郁金香BBS站 (2004年12月02日23:01:37 星期四), 站内信件
Posted by kreny at May 19, 2004 07:04 PM
Trackback URL: http://weblog.dalouis.com/cgi-bin/mt-tb.cgi/64
linux的命令行可以胜任所有的工作,这和ms的产品有着很大的区别,到现在为止仍然有
很多的爱好者对敲键盘乐此不疲,而在繁重的管理工作和键盘工作中,正则表达式对于
简化工作起到了很大的作用。
Perl regular expressions man page.
http://www.perldoc.com/perl5.8.0/pod/perlre.html
一、正则表达式简介
事实上,正则表达式不仅适用于linux,多种编程语言中也可以使用到它,因为它实际上
是人们对于某种规律的表达方式。
如果要把他的所有应用都讲上的话那这篇文章会变的太长以至于无法阅读,我只介绍他
在linux下和几种最重要的命令的搭配使用。
基本的元字符集:
^行首
$行尾
*匹配星号前的字符一次或多次
[]匹配[]内的字符,可以是一个字符也可以是字符列
/用来屏蔽一个元字符的特殊含义,可以使其失去原有的意义。
pattern/{n/}用来匹配前面pattern出现的次数。n为次数。
而其中使用最多的是行首和行尾,无论在任何地方都可能会用到它们,比如vi,你输入$
,就可以跳到行尾,在bbs上,你也可以输入$,直接跳到这个版的最后的一篇文章。
后面所说的将是他们的和具体命令结合的例子。
二、grep 和正则表达式
grep是个非常常用的工具,linux其实和internet一样,都是一个充满了大量信息、数据
的东西,如何有效的过滤自己不用的信息、获取有用的信息反映了一个人水平的高低,
当我还是linux新手的时候还不懂得用grep呢。
一个最简单的应用例子就是如何查看一个目录里只查看文件夹了,ls并没有提供这样的
参数给你,而是需要你用grep(或后面提到的awk)来实现这样的功能。我们知道一个文
件夹的属性为dxxx,所以我们可以用ls -l |grep ^d,即打印匹配行首第一个字母为d的
项目,这样就把所有的文件夹打印出来而忽略其他非文件夹的文件了,举一反三,我们
可以用来匹配所有的权限,比如我想找到所有权限为rwx------的文件,这样我们就可以
输入ls -l|grep ^.rwx,其中.号为匹配任意一个字符。再看下面的例子,想找权限为--
--rw----的文件,可以使用ls -l|grep ^....rw....,怎么样,这样简单多了吧,我们
还可以寻找所有以*号结尾的文件(在某些linux上用它来代表可执行文件)即ls |grep
/*$,要注意的是必须加/以屏蔽*号的原来的特殊意义,而$号是加在行尾的。
可以用^符号来再非正则表达式的意思(即否定)如前面我说了要看文件夹,那么如果我
想看不是文件夹的文件怎么办 : ls -l|grep ^[^d],这样的意思就是说查看所有行首不
为d字母的项,当然也可以用grep 的-v选项实现同样功能。不过今天重点是说正则表达
式,所以就不讲参数了。
我还可以查找多个文件,如有一个目录里面有我需要的内容,我只知道他在某个.doc文
件里头,我可以用grep "表达式" *.doc,而这个表达式就需要你去想了,有多种方法可
以指定模糊的表达式,如k...D,代表以小写字母k开头,中间三个是任意字符而以大写
字母D结尾的字符串,而k*D,则表达以k开头中间可以是任意长度任意字符的而以D结尾
的字符串,还可以用[]指定范围,如[12345]day,指的是以1到6中任意一个字符开头后
面是day的字符串,像3day就匹配这个表达式而13day就不匹配。[Ss]可以指定以大写S或
者小写s的字符,而像结合pattern/{n/}还可以用更奇妙的用法,我就不多说了。
三、awk和正则表达式
awk对于从大的数据文件中抽取指定的数据包十分有用,比如你可以用他来管理passwd文
件,或者是日志文件(相当巨大的文件,而用了awk就会变的很轻松了),通常awk都是
和grep结合来用的,又grep抽出行,再有awk抽出行中指定的列,不过就算单独用awk也
一样好用。请看看这样的例子
awk -F: '{if($6 ~ /bash/) print $0}' /etc/passwd
这是个相当复杂的例子,我举这个例子的目的只是为了说明结合命令语法和正则表达式
可以实现相当强的过滤作用,这个命令的作用是从passwd文件中的第六列中抽取所有含
有bash的项目然后在打印这些项目的第一项即他们的用户名。我假设passwd为这样的内
容
root:*:*:*:*:*:/bin/bash
user:*:*:*:*:*:/bin/bash
xie:*:*:*:*:*:/bin/csh
ftp:*:*:*:*:*:/bin/zsh
那么输出就应该为
root
user
我们逐个来分析,首先 -F:指定:为分隔符,因为默认的分隔符是空格,然后我们用一个
假设语句,因为假设语句和后面的print组合成一个动作,所以必须用花括号括起来,意
思是如果(if)第六列($6)匹配(~)字符串bash,那么打印(print)第零列($0)。
其中/bash/指的是匹配bash,//只是起括起来的作用,并不参与判断。
awk有自己的正则表达式和条件操作符,他比一般的正则表达式要多出两个元字符,就是
+和?,+使用匹配一个或多个字符。?匹配模式出现频率,例如使用/XY?Z/匹配XYZ,或Y
Z。条件操作符有
<小于
<=小于等于
==等于(这个和C语言是一样的)
!=不等于
>=大于等于
~匹配正则表达式
!~不匹配正则表达式
结合以上表达式,还可以作出更多的动作,如
ls -l|awk 'BEGIN {print "Name/t SIZE"} {if /^[^d]/} {print $9 "/t" $5}
{tot+=5} END {print "total KB:"tot}'
可以用此表达式来打印文件名几其长度,然后输出所有文件加起来的大小。
他相当与于我前面所说的先找出不是文件夹的文件,然后打印他们的大小和长度,把这
些大小值放入变量tot中,放一次加一次(+=),最后打印tot,就可以把所有文件的大
小求出来了。
逻辑符号
&& AND,必须同时为真
! 非,求逆
awk '{if ($3=="root" && $5="/root") print $0}' /etc/passwd
当组和个人目录都为root的时候打印用户的名字。
嘿嘿,事实上awk还有算术操作符呢,我为了偷懒就不写了,不过上面已经有例子了(用
了+=),就留给大家慢慢研究吧。
四、VI和正则表达式
文书编辑更加用用到正则表达式了,比如说在编辑状态下输入^,可以跳到行中第一个非
空字符,输入$,可以跳到本行行尾(在行号表示的时候,$代表最后一行)。输入/可以
搜索字符串,同样可以使用正则表达式匹配,如/^str,则匹配行首的str,输入/str$,
则匹配行尾的str。其他的和正则表达式方法一样。
五、总结
linux还有更复杂的sed也会用到正则表达式,事实上大部分和信息过滤有关的都离不开
他,不过小子才疏学浅,实在是写不了了,仅以此文抛砖引玉,不过各位大侠可千万别
因为我这篇文章写的差而全把砖头往我招呼啊……
还有一点是给初学者的:记得多用|管道和文件操作符啊,0代表标准输入、1代表标准输
出、2代表错误输出,其他还有3-9你是可以任意使用的,如可以先把某文件指到操作符4
,再把4指向0,那么就可以作为程序的输入了。
--
│ ◢◣ ╭──╮ ╭╮╭╮ ╭╮ ╭──╮ ◣◢ │
│ ◥◤ │╭─╯ ││││ ╰╯ ╰┐┌╯ ◥██◤ │
│ ╰╮ │╰─╮ ◢ ││││ ◢╭╭╮─╮◤ ││ ◢◥█◣ │
│ ╭┴─╰─╮│─╮ ││││◥╭─╯││◥╰─ ││─━╮◤ │ │
│ -┺━ ╭─╯│◥╰─│╰╯│─╯◥ ││*,.*,.*││ ◥╰──╯ │
│ ^^"^^"^ ╰──╯^"^^"^╰──╯"^^"^^"^╰╯"^^"^^"╰╯^"^^"^"^^"^"^^ │
※ 来源:·郁金香BBS站 bbs.stu.edu.cn·[FROM: 郁金香BBS站]