linux 正则表达式
一. grep和egrep
作用:文本过滤
grep
[root@www ~]# grep [-vnicEwo][-A] [-B] [--color=auto] '搜寻字串' filename
选项与参数:
# -A :后面可加数字,为 after 的意思,除了列出该行外,后续的 n 行也列出来;
# -B :后面可加数字,为 befer 的意思,除了列出该行外,前面的 n 行也列出来;
# -v 排除不包括匹配文件的内容 # -n 显示匹配行及行号 # -i 不区分大小写(只适用于单字符),默认区分大小写 # -c 只统计匹配的行数,注意不是次数 # -E 使用扩展的egrep命令 # --color=auto 为grep匹配过的字符串添加颜色 # -w 只匹配过滤的单词 # -o 只输出匹配的内容
特殊符号 代表意义 [:alnum:] 代表英文大小写字节及数字,亦即 0-9, A-Z, a-z [:alpha:] 代表任何英文大小写字节,亦即 A-Z, a-z [:blank:] 代表空白键与 [Tab] 按键两者 [:cntrl:] 代表键盘上面的控制按键,亦即包括 CR, LF, Tab, Del.. 等等 [:digit:] 代表数字而已,亦即 0-9 [:graph:] 除了空白字节 (空白键与 [Tab] 按键) 外的其他所有按键 [:lower:] 代表小写字节,亦即 a-z [:print:] 代表任何可以被列印出来的字节 [:punct:] 代表标点符号 (punctuation symbol),亦即:" ' ? ! ; : # $... [:upper:] 代表大写字节,亦即 A-Z [:space:] 任何会产生空白的字节,包括空白键, [Tab], CR 等等 [:xdigit:] 代表 16 进位的数字类型,因此包括: 0-9, A-F, a-f 的数字与字节
#范例 1)grep -v "root" test1.txt #过滤不包含root的字符,默认是以行为单位,排除包含过滤字符的行。 2)grep -n "root" test1.txt #输出包含root字符的行,并显示出行号。 3)grep -i “root” test2.txt #使用-i参数不区分大小写过滤root。 4)grep -Ei --color=auto "root | wang" test2.txt #不区分大小写同时过滤root和wang,并增加颜色显示。 5)grep -c “root” test2.txt #计算匹配root字符串的数量。 6)grep -o “root” test2.txt #只输出匹配的内容。 7)grep -w “root” /etc/passwd #只匹配过滤的单词,如果不加-w,则与过滤单词相似的行业会被显示出。
范例一:用 dmesg 列出核心信息,再以 grep 找出内含 eth 那行 [root@www ~]# dmesg | grep 'eth' eth0: RealTek RTL8139 at 0xee846000, 00:90:cc:a6:34:84, IRQ 10 eth0: Identified 8139 chip type 'RTL-8139C' eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1 eth0: no IPv6 routers present # dmesg 可列出核心产生的信息!透过 grep 来撷取网络卡相关资讯 (eth) , # 就可发现如上资讯。不过没有行号与特殊颜色显示!看看下个范例吧! 范例二:承上题,要将捉到的关键字显色,且加上行号来表示: [root@www ~]# dmesg | grep -n --color=auto 'eth' 247:eth0: RealTek RTL8139 at 0xee846000, 00:90:cc:a6:34:84, IRQ 10 248:eth0: Identified 8139 chip type 'RTL-8139C' 294:eth0: link up, 100Mbps, full-duplex, lpa 0xC5E1 305:eth0: no IPv6 routers present # 你会发现除了 eth 会有特殊颜色来表示之外,最前面还有行号喔! 范例三:承上题,在关键字所在行的前两行与后三行也一起捉出来显示 [root@www ~]# dmesg | grep -n -A3 -B2 --color=auto 'eth' 245-PCI: setting IRQ 10 as level-triggered 246-ACPI: PCI Interrupt 0000:00:0e.0[A] -> Link [LNKB] ... 247:eth0: RealTek RTL8139 at 0xee846000, 00:90:cc:a6:34:84, IRQ 10 248:eth0: Identified 8139 chip type 'RTL-8139C' 249-input: PC Speaker as /class/input/input2 250-ACPI: PCI Interrupt 0000:00:01.4[B] -> Link [LNKB] ... 251-hdb: ATAPI 48X DVD-ROM DVD-R-RAM CD-R/RW drive, 2048kB Cache, UDMA(66) # 如上所示,你会发现关键字 247 所在的前两行及 248 后三行也都被显示出来! # 这样可以让你将关键字前后数据捉出来进行分析啦!
[root@study study]# grep -n 't[ae]st' grepstudy.txt #tast或test 15:I can't finish the test.^M 17:Oh! The soup taste good.^M [root@study study]# grep -n 'oo' grepstudy.txt 1:"Open Source" is a good mechanism to develop programs. 3:apple is my favorite food. 5:Football game is not use feet only. 17:Oh! The soup taste good.^M 35:google is the best tools for search keyword. 37:goooooogle yes! [root@study study]# grep -n '[^g]oo' grepstudy.txt #非g开头的oo 3:apple is my favorite food. 5:Football game is not use feet only. 35:google is the best tools for search keyword. 37:goooooogle yes! [root@study study]# grep -n '[^a-z]oo' grepstudy.txt 非小写字母开头的oo 5:Football game is not use feet only. [root@study study]# grep -n '[0-9]' grepstudy.txt #所有数字 9:However, this dress is about $ 3183 dollars.^M 29:You are the best is mean you are the no. 1. [root@study study]# grep -n '^the' grepstudy.txt #以the开头 23:the symbol '*' is represented as start. [root@study study]# grep -n '^[a-z]' grepstudy.txt #以小写字母开头 3:apple is my favorite food. 7:this dress doesn't fit me. 19:motorcycle is cheap than car. 23:the symbol '*' is represented as start. 35:google is the best tools for search keyword. 37:goooooogle yes! 39:go! go! Let's go. [root@study study]# grep -n '^[^a-zA-Z]' grepstudy.txt #以字母开头 1:"Open Source" is a good mechanism to develop programs. [root@study study]# grep -n '\.$' grepstudy.txt #以.结尾 1:"Open Source" is a good mechanism to develop programs. 3:apple is my favorite food. 5:Football game is not use feet only. 7:this dress doesn't fit me. 19:motorcycle is cheap than car. 21:This window is clear. 23:the symbol '*' is represented as start. 29:You are the best is mean you are the no. 1. 31:The world <Happy> is the same with "glad". 33:I like dog. 35:google is the best tools for search keyword. 39:go! go! Let's go. [root@study study]# grep -n '^$' grepstudy.txt #查找空白行 2: [root@study study]# grep -v '^$' /root/study/123 | grep -v '^#' #去空白和注释行 # . (小数点):代表『一定有一个任意字节』的意思; # * (星星号):代表『重复前一个字节, 0 到无穷多次』的意思,为组合形态 [root@study study]# grep -n 'g.d' grepstudy.txt #gg之间一个任意字符 [root@study study]# grep -n 'g..d' grepstudy.txt #gg之间2个任意字符 1:"Open Source" is a good mechanism to develop programs. 17:Oh! The soup taste good.^M [root@study study]# grep -n 'g...d' grepstudy.txt #gg之间3个任意字符 43:====goood---- 25:Oh! My god! #如下几个范例连起来看: [root@study study]# grep -n 'o*' grepstudy.txt #全部显示 1:"Open Source" is a good mechanism to develop programs. 2: 3:apple is my favorite food. 4: ……更多省略…… [root@study study]# grep -n 'oo*' grepstudy.txt #1个o后0-∞个o 1:"Open Source" is a good mechanism to develop programs. 3:apple is my favorite food. 5:Football game is not use feet only. 7:this dress doesn't fit me. 9:However, this dress is about $ 3183 dollars.^M 11:GNU is free air not free beer.^M 17:Oh! The soup taste good.^M 19:motorcycle is cheap than car. 21:This window is clear. 23:the symbol '*' is represented as start. 25:Oh! My god! 27:The gd software is a library for drafting programs.^M 29:You are the best is mean you are the no. 1. 31:The world <Happy> is the same with "glad". 33:I like dog. 35:google is the best tools for search keyword. 37:goooooogle yes! 39:go! go! Let's go. 41:this last line: goooooood 43:====goood---- 45:--===gooood-== [root@study study]# grep -n 'ooo*' grepstudy.txt #2个o后0-∞个o 1:"Open Source" is a good mechanism to develop programs. 3:apple is my favorite food. 5:Football game is not use feet only. 17:Oh! The soup taste good.^M 35:google is the best tools for search keyword. 37:goooooogle yes! 41:this last line: goooooood 43:====goood---- 45:--===gooood-== [root@study study]# grep -n 'oooo*' grepstudy.txt #3个o后0-∞个o 37:goooooogle yes! 41:this last line: goooooood 43:====goood---- 45:--===gooood-== [root@study study]# grep -n 'g*g' grepstudy.txt # 第一个g是0到∞,第二个g精确匹配。 1:"Open Source" is a good mechanism to develop programs. 5:Football game is not use feet only. 17:Oh! The soup taste good.^M 25:Oh! My god! 27:The gd software is a library for drafting programs.^M 31:The world <Happy> is the same with "glad". 33:I like dog. 35:google is the best tools for search keyword. 37:goooooogle yes! 39:go! go! Let's go. 41:this last line: goooooood 43:====goood---- 45:--===gooood-== [root@study study]# grep -n 'g.*g' grepstudy.txt #gg以及gg之间的任意字符 1:"Open Source" is a good mechanism to develop programs. 27:The gd software is a library for drafting programs.^M 35:google is the best tools for search keyword. 37:goooooogle yes! 39:go! go! Let's go. [root@study study]# grep -n '[0-9][0-9]*' grepstudy.txt #匹配数字 9:However, this dress is about $ 3183 dollars.^M 29:You are the best is mean you are the no. 1. [root@study study]# grep -n 'o\{2\}' grepstudy.txt #匹配2个o 1:"Open Source" is a good mechanism to develop programs. 3:apple is my favorite food. 5:Football game is not use feet only. 17:Oh! The soup taste good.^M 35:google is the best tools for search keyword. 37:goooooogle yes! 41:this last line: goooooood 43:====goood---- 45:--===gooood-== [root@study study]# grep -n 'go\{2,5\}g' grepstudy.txt 匹配g 2-5个o g 35:google is the best tools for search keyword.
经过以上grep进阶用法实战范例的使用,可以将grep正则表示法表示如下(融汇贯通):
RE 字符 | 意义与范例 |
^word | 意义:待搜寻的字串(word)在行首! 范例:搜寻行首为 # 开始的那一行,并列出行号 grep -n '^#' regular_express.txt |
word$ | 意义:待搜寻的字串(word)在行尾! 范例:将行尾为 ! 的那一行列印出来,并列出行号 grep -n '!$' regular_express.txt |
. | 意义:代表『一定有一个任意字节』的字符! 范例:搜寻的字串可以是 (eve) (eae) (eee) (e e), 但不能仅有 (ee) !亦即 e 与 e 中间『一定』仅有一个字节,而空白字节也是字节! grep -n 'e.e' regular_express.txt |
\ | 意义:跳脱字符,将特殊符号的特殊意义去除! 范例:搜寻含有单引号 ' 的那一行! grep -n \' regular_express.txt |
* | 意义:重复零个到无穷多个的前一个 RE 字符 范例:找出含有 (es) (ess) (esss) 等等的字串,注意,因为 * 可以是 0 个,所以 es 也是符合带搜寻字串。另外,因为 * 为重复『前一个 RE 字符』的符号, 因此,在 * 之前必须要紧接著一个 RE 字符喔!例如任意字节则为 『.*』 ! grep -n 'ess*' regular_express.txt |
[list] | 意义:字节集合的 RE 字符,里面列出想要撷取的字节! 范例:搜寻含有 (gl) 或 (gd) 的那一行,需要特别留意的是,在 [] 当中『谨代表一个待搜寻的字节』, 例如『 a[afl]y 』代表搜寻的字串可以是 aay, afy, aly 即 [afl] 代表 a 或 f 或 l 的意思! grep -n 'g[ld]' regular_express.txt |
[n1-n2] | 意义:字节集合的 RE 字符,里面列出想要撷取的字节范围! 范例:搜寻含有任意数字的那一行!需特别留意,在字节集合 [] 中的减号 - 是有特殊意义的,他代表两个字节之间的所有连续字节!但这个连续与否与 ASCII 编码有关,因此,你的编码需要配置正确(在 bash 当中,需要确定 LANG 与 LANGUAGE 的变量是否正确!) 例如所有大写字节则为 [A-Z] grep -n '[A-Z]' regular_express.txt |
[^list] | 意义:字节集合的 RE 字符,里面列出不要的字串或范围! 范例:搜寻的字串可以是 (oog) (ood) 但不能是 (oot) ,那个 ^ 在 [] 内时,代表的意义是『反向选择』的意思。 例如,我不要大写字节,则为 [^A-Z]。但是,需要特别注意的是,如果以 grep -n [^A-Z] regular_express.txt 来搜寻,却发现该文件内的所有行都被列出,为什么?因为这个 [^A-Z] 是『非大写字节』的意思, 因为每一行均有非大写字节,例如第一行的 "Open Source" 就有 p,e,n,o.... 等等的小写字 grep -n 'oo[^t]' regular_express.txt |
\{n,m\} | 意义:连续 n 到 m 个的『前一个 RE 字符』 意义:若为 \{n\} 则是连续 n 个的前一个 RE 字符, 意义:若是 \{n,\} 则是连续 n 个以上的前一个 RE 字符! 范例:在 g 与 g 之间有 2 个到 3 个的 o 存在的字串,亦即 (goog)(gooog) grep -n 'go\{2,3\}g' regular_express.txt |
再次强调:『正规表示法的特殊字节』与一般在命令列输入命令的『万用字节』并不相同, 例如,在万用字节当中的 * 代表的是『 0 ~ 无限多个字节』的意思,但是在正规表示法当中, * 则是『重复 0 到无穷多个的前一个 RE 字符』的意思~使用的意义并不相同,不要搞混了!
egrep
扩展正则表达式方法。
grep -v '^$' regular_express.txt | grep -v '^#' 需要使用到管线命令来搜寻两次!那么如果使用延伸型的正则表示法,我们可以简化为: egrep -v '^$|^#' regular_express.txt
RE 字符 | 意义与范例 |
+ | 意义:重复『一个或一个以上』的前一个 RE 字符 范例:搜寻 (god) (good) (goood)... 等等的字串。 那个 o+ 代表『一个以上的 o 』所以,底下的运行成果会将第 1, 9, 13 行列出来。 egrep -n 'go+d' regular_express.txt |
? | 意义:『零个或一个』的前一个 RE 字符 范例:搜寻 (gd) (god) 这两个字串。 那个 o? 代表『空的或 1 个 o 』所以,上面的运行成果会将第 13, 14 行列出来。 有没有发现到,这两个案例( 'go+d' 与 'go?d' )的结果集合与 'go*d' 相同? 想想看,这是为什么喔! ^_^ egrep -n 'go?d' regular_express.txt |
| | 意义:用或( or )的方式找出数个字串 范例:搜寻 gd 或 good 这两个字串,注意,是『或』! 所以,第 1,9,14 这三行都可以被列印出来喔!那如果还想要找出 dog 呢? egrep -n 'gd|good' regular_express.txt |
() | 意义:找出『群组』字串 范例:搜寻 (glad) 或 (good) 这两个字串,因为 g 与 d 是重复的,所以, 我就可以将 la 与 oo 列於 ( ) 当中,并以 | 来分隔开来,就可以啦! egrep -n 'g(la|oo)d' regular_express.txt |
()+ | 意义:多个重复群组的判别 范例:将『AxyzxyzxyzxyzC』用 echo 叫出,然后再使用如下的方法搜寻一下! echo 'AxyzxyzxyzxyzC' | egrep 'A(xyz)+C'上面的例子意思是说,我要找开头是 A 结尾是 C ,中间有一个以上的 "xyz" 字串的意思~ |
以上这些就是延伸型的正规表示法的特殊字节。另外,要特别强调的是,那个 ! 在正规表示法当中并不是特殊字节, 所以,如果你想要查出来文件中含有 ! 与 > 的字行时,可以这样:
grep -n '[!>]' regular_express.txt
常常看到有陷阱的题目写:『反向选择这样对否? '[!a-z]'?』, 呵呵!是错的~要 '[^a-z] 才是对的。
二. sed
作用:字符流编辑器
[root@www ~]# sed [-nefr] [动作] 选项与参数: -n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到萤幕上。但如果加上 -n 参数后,则只有经过 sed 特殊处理的那一行(或者动作)才会被列出来。 -e :直接在命令列模式上进行 sed 的动作编辑; -f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作; -r :sed 的动作支持的是延伸型正则表示法的语法。(默认是基础正则表示法语法) -i :直接修改读取的文件内容,而不是由屏幕输出。 动作说明: [n1[,n2]]function n1, n2 :不见得会存在,一般代表『选择进行动作的行数』,举例来说,如果我的动作 是需要在 10 到 20 行之间进行的,则『 10,20[动作行为] 』 function 有底下这些咚咚: a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行! d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚; i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~ s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配 正规表示法!例如 1,20s/old/new/g 就是啦!
1)sed '2a 106,tom,student' persons.txt #在persons.txt文件的第二行后追加一行内容106,tom,student; #如果a参数还成i则是在行前插入106,tom,student; #如果要在2行后追加多行,则内容A和内容B之间要使用/n换行; 2)sed '2d' person.txt #删除person文件中的第二行; 3)sed '2,5d' person.txt #删除person文件中的第二到第五行; 4)sed 's/tom/jet/g' person.txt #将person.txt文件中的所有tom替换成jet; 5)sed -n '2p' person.txt #打印person.txt的第二行内容,这里一定要加-n参数,否则会默认打印出文件所有内容; 6)sed 'N;s#\n#=#g' test.txt 将转换如下两种格式; aaaaaa bbbbb aaaaaa bbbbb aaaaa=bbbbb aaaaa=bbbbb
#范例一:将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除! [root@www ~]# nl /etc/passwd | sed '2,5d' 1 root:x:0:0:root:/root:/bin/bash 6 sync:x:5:0:sync:/sbin:/bin/sync 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown .....(后面省略)..... 看到了吧?sed 的动作为 '2,5d' ,那个 d 就是删除!因为 2-5 行给他删除了,所以显示的数据就没有 2-5 行罗~ 另外,注意一下,原本应该是要下达 sed -e 才对,没有 -e 也行啦!同时也要注意的是, sed 后面接的动作,请务必以 '' 两个单引号括住喔! 如果题型变化一下,举例来说,如果只要删除第 2 行,可以使用『 nl /etc/passwd | sed '2d' 』来达成, 至於若是要删除第 3 到最后一行,则是『 nl /etc/passwd | sed '3,$d' 』的啦,那个钱字号『 $ 』代表最后一行! #范例二:承上题,在第二行后(亦即是加在第三行)加上『drink tea?』字样! [root@www ~]# nl /etc/passwd | sed '2a drink tea' 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin drink tea 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin .....(后面省略)..... #范例三:在第二行后面加入两行字,例如『Drink tea or .....』与『drink beer?』 [root@www ~]# nl /etc/passwd | sed '2a Drink tea or ......\n drink beer ?' 1 root:x:0:0:root:/root:/bin/bash 2 bin:x:1:1:bin:/bin:/sbin/nologin Drink tea or ...... drink beer ? 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin .....(后面省略)..... #范例四:我想将第2-5行的内容取代成为『No 2-5 number』呢? [root@www ~]# nl /etc/passwd | sed '2,5c No 2-5 number' 1 root:x:0:0:root:/root:/bin/bash No 2-5 number 6 sync:x:5:0:sync:/sbin:/bin/sync .....(后面省略)..... #范例五:仅列出 /etc/passwd 文件内的第 5-7 行 [root@www ~]# nl /etc/passwd | sed -n '5,7p' 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 6 sync:x:5:0:sync:/sbin:/bin/sync 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdow
# 部分数据的搜寻并取代的功能 # sed 's/要被取代的字串/新的字串/g' 范例1:查看的接口只输出IP,AWK更简单,但这里是为举例而已。 [root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr' | \ > sed 's/^.*addr://g' | sed 's/Bcast.*$//g' 192.168.1.100 #范例2 注释---转空白---去空白 [root@www ~]# cat /etc/man.config | grep 'MAN'| sed 's/#.*$//g' | \ > sed '/^$/d' MANPATH /usr/man MANPATH /usr/share/man MANPATH /usr/local/man ....(后面省略).... #范例六:利用 sed 将 regular_express.txt 内每一行结尾若为 . 则换成 ! [root@www ~]# sed -i 's/\.$/\!/g' regular_express.txt #范例七:利用 sed 直接在 regular_express.txt 最后一行加入『# This is a test』 [root@www ~]# sed -i '$a # This is a test' regular_express.txt
三. awk
作用:文件的格式化处理
#语法格式:awk [option] 'pattern{action}' file #参数选项 解释说明 #-F 指定字段分隔符 #-v 定义或修改一个awk的内部变量 1)awk 'NR==5' jet.txt #打印显示第5行内容 2)awk 'NR==2,NR==6' jet.txt #打印显示第2行到第6行的内容 3)awk '{print NR,$0}' jet.txt #用awk实现每行内容之前加上行号 4)awk 'NR==3,NR==6 {print NR,$0}' jet.txt #用awk实现显示第三行到第六行内容之前加上行号 5)awk -F “:” '{print $1,$3,$NF}' jet.txt #显示jet文件的第一列,第三列,最后一列 6)awk'{gsub("/sbin/nologin","/bin/bash",$0);print $0}' jet.txt #把文件中的/sbin/nologin替换成为/bin/bash; #gsub函数的格式如下: gsub("替换对象","替换成什么内容",哪一列) ①gsub与后面的括号之间不能有空格; ②"替换对象","替换成什么内容",哪一列之间要用逗号分隔开; ③替换对象和被替换对象需要用“”包起来,用逗号隔开; ④最后一列可以省略,相当于写上了$0,$0代表整行内容; 7)ifconfig eth0 | awk -F "(addr:) | ( Bcast:)" 'NR==2{print $2}' 或 ifconfig eht0 | awk -F "[ :]+" 'NR==2{print $4}' #提取ifconfig中的IP地址 8)awk -F "/" '{print $3}' jet.txt | sort | uniq -c #取出jet文件中的域名,并排序,然后去重计数;
四、其他命令
vimdiff 与diff
[root@www ~]# diff [-bBi] from-file to-file 选项与参数: from-file :一个档名,作为原始比对文件的档名; to-file :一个档名,作为目的比对文件的档名; 注意,from-file 或 to-file 可以 - 取代,那个 - 代表『Standard input』之意。 -b :忽略一行当中,仅有多个空白的差异(例如 "about me" 与 "about me" 视为相同 -B :忽略空白行的差异。 -i :忽略大小写的不同。