- 概述:
正则表达式基本上是一种“表达式”, 只要工具程序支持这种表达式,那么该工具程序就可以用来作为正则表达式的字串处理之用。 例如 vi, grep, awk,sed 等等工具,因为她们有支持正则表达式, 所以,这些工具就可以使用正则表达式的特殊字符来进行字串的处理。 -
grep
参数:
-n:行号
-v:反选
-i:忽略大小写
-A :后面可加数字,为 after 的意思,除了列出该行外,后续的 n 行也列出来;
-B :后面可加数字,为 befer 的意思,除了列出该行外,前面的 n 行也列出来;
–color=auto 可将正确的那个撷取数据列出颜色# 用dmesg列出核心信息,再以grep找出内含eth的那行 [root@CentOS ~]# dmesg | grep eth udev: renamed network interface eth0 to rename2 udev: renamed network interface eth1 to rename3 udev: renamed network interface rename2 to eth1 udev: renamed network interface eth2 to eth3 udev: renamed network interface rename3 to eth2 eth2: no IPv6 routers present eth3: no IPv6 routers present # 承上,用关键字显示,并且加上行号 [root@CentOS ~]# dmesg | grep -n --color=auto eth 1450:udev: renamed network interface eth0 to rename2 1453:udev: renamed network interface eth1 to rename3 1454:udev: renamed network interface rename2 to eth1 1455:udev: renamed network interface eth2 to eth3 1456:udev: renamed network interface rename3 to eth2 1497:eth2: no IPv6 routers present 1498:eth3: no IPv6 routers present # 承上,在关键字所在行的前两行与后三行也一起找出来显示 [root@CentOS ~]# dmesg | grep -n -A3 -B2 --color=auto eth 1448-sd 0:0:0:0: Attached scsi generic sg0 type 0 1449-sr 2:0:0:0: Attached scsi generic sg1 type 5 1450:udev: renamed network interface eth0 to rename2 1451-parport_pc 00:09: reported by Plug and Play ACPI 1452-parport0: PC-style at 0x378, irq 7 [PCSPP,TRISTATE] 1453:udev: renamed network interface eth1 to rename3 1454:udev: renamed network interface rename2 to eth1 1455:udev: renamed network interface eth2 to eth3 1456:udev: renamed network interface rename3 to eth2 1457-ENS1371 0000:02:02.0: PCI INT A -> GSI 16 (level, low) -> IRQ 16 1458-ppdev: user-space parallel port driver 1459-microcode: CPU0 sig=0x40651, pf=0x1, revision=0x10
grep 在数据中查寻一个字串时,是以 “整行” 为单位来进行数据的撷取的!”# 将命令别名加入配置文件 [root@CentOS ~]# alias grep='grep --color=auto' [root@CentOS ~]# source ~/.bashrc
使用前的准备:
1 . 语系已经使用“ export LANG=C; export LC_ALL=C ”的设置值; grep 已经使用 alias 设置成为“
2 . grep –color=auto ”查找特定字符串
# 匹配含有“the”的行 [root@CentOS Desktop]# grep -n 'the' regular_express.txt # 匹配不含“the”的行 [root@CentOS Desktop]# grep -n -v 'the' regular_express.txt # 匹配“the”且忽略大小写 [root@CentOS Desktop]# grep -n -i 'the' regular_express.txt
利用中括号[]来查找集合字符
# 匹配含test或test的行 [root@CentOS Desktop]# grep -n 't[ae]st' regular_express.txt # 匹配含有00的行 [root@CentOS Desktop]# grep -n 'oo' regular_express.txt 1:"Open Source" is a good mechanism to develop programs. 3:Football game is not use feet only. 19:goooooogle yes! # 注意会匹配oooooo的行,只要含有oo就会匹配 # 匹配oo前非g的行 [root@CentOS Desktop]# grep -n '[^g]oo' regular_express.txt 2:apple is my favorite food. 3:Football game is not use feet only. 18:google is the best tools for search keyword. 19:goooooogle yes! # 匹配oo前非小写字符的行 [root@CentOS Desktop]# grep -n '[^a-z]oo' regular_express.txt [root@CentOS Desktop]# grep -n '[^[:lower:]]oo' regular_express.txt # 匹配含有数字的行 [root@CentOS Desktop]# grep -n '[0-9]' regular_express.txt [root@CentOS Desktop]# grep -n '[[:digit:]]' regular_express.txt
行首与行位^$
'^the':引号中^代表行首 [^the]:括号中用^代表反选 # 匹配开头是the的行 [root@CentOS Desktop]# grep -n '^the' regular_express.txt # 匹配开头是小写字母的行 [root@CentOS Desktop]# grep -n '^[a-z]' regular_express.txt [root@CentOS Desktop]# grep -n '^[[:lower:]]' regular_express.txt # 匹配开头非字母的行 [root@CentOS Desktop]# grep -n '^[^a-zA-Z]' regular_express.txt # 匹配行尾为小数点的行 [root@CentOS Desktop]# grep -n '\.$' regular_express.txt # 小数点是特殊字符,需要转义字符转义 # 用cat -A 查看断行字符是否为$ # 将^M的断行字符转换成$ [root@CentOS Desktop]# cat regular_express.txt | tr -d "^V^M" > regular_express2.txt # 找出空白行 [root@CentOS Desktop]# grep -n '^$' regular_express.txt # 不要空白行且不要注释行 [root@CentOS Desktop]# grep -v '^$' regular_express.txt | grep -v '^#' # grep需要匹配两次时,不能写在一起,可以用管道
任意一个字符与重复字符
(小数点.):代表“一定有一个任意字符”的意思;
(星星号*):代表“重复前一个字符, 0 到无穷多次”的意思,为组合形态。
.:任意字符
*:重复任意次前面的字符
.*:任意个任意字符
o*:具有空字符或者一个o以上的字符
oo*:第一个o肯定存在,第二个o则是可有可无的多个o# 匹配g和d之间有两个任意字符的行 [root@CentOS Desktop]# grep -n 'g..d' regular_express.txt # 匹配至少两个o以上的字符 [root@CentOS Desktop]# grep -n 'ooo*' regular_express.txt 1:"Open Source" is a good mechanism to develop programs. 18:google is the best tools for search keyword. 19:goooooogle yes! # 匹配2个g之间至少存在一个o的行 [root@CentOS Desktop]# grep -n 'goo*g' regular_express.txt 18:google is the best tools for search keyword. 19:goooooogle yes! # 匹配空格加一个g或者一个以上g加上g的行 [root@CentOS Desktop]# grep -n 'g*g' regular_express.txt 17:I like dog. 18:google is the best tools for search keyword. 19:goooooogle yes! 20:go! go! Let's go. # g*g:空字符或者一个以上g然后后面加上g,匹配g,gg,ggg,gggg # 匹配存在任意数字的行 # 下面两个相同 [root@CentOS Desktop]# grep -n '[0-9][0-9]*' regular_express.txt [root@CentOS Desktop]# grep -n '[0-9]' regular_express.txt
限定连续RE字符范围{}
# 匹配存在两个o的行 [root@CentOS Desktop]# grep -n 'o\{2\}' regular_express.txt # 匹配g后接2到5个o再接一个g的行 [root@CentOS Desktop]# grep -n 'go\{2,5\}g' regular_express.txt 18:google is the best tools for search keyword. # [root@CentOS Desktop]# grep -n 'gooo*g' regular_express.txt # 会出现“goo g”的情况
基础正则表达式字符
# 列出以a开头的字符 [root@CentOS Desktop]# ls /root | grep -n '^a.*' [root@CentOS Desktop]# ls a*
sed的用法
参数:
-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到屏幕上。
但如果加上 -n 参数后,则只有经过 sed 特殊处理的那一行(或者动作)才会被列出来。
-e :直接在命令行界面上进行 sed 的动作编辑;
-f :直接将 sed 的动作写在一个文件内, -f filename 则可以执行 filename 内的 sed 动作;
-r :sed 的动作支持的是延伸型正则表达式的语法。(默认是基础正则表达式语法)
-i :直接修改读取的文件内容,而不是由屏幕输出。(修改文件的操作)
动作说明:(只是修改屏幕输出结果,文件没变)
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 就是# 给文本加行号,两个相同 [root@CentOS Desktop]# nl regular_express.txt [root@CentOS Desktop]# cat -n regular_express.txt # 显示时删除2到5行 [root@CentOS Desktop]# nl regular_express.txt | sed '2,5d' # 删除第二行 [root@CentOS Desktop]# nl regular_express.txt | sed '2d' # 删除3到最后一行 [root@CentOS Desktop]# nl regular_express.txt | sed '3,$d' # 在第二行后加一行 [root@CentOS Desktop]# nl regular_express.txt | sed '2a grink tea' 1 "Open Source" is a good mechanism to develop programs. 2 apple is my favorite food. grink tea 3 Football game is not use feet only. # 在第二行前增加一行 [root@CentOS Desktop]# nl regular_express.txt | sed '2i grink tea' 1 "Open Source" is a good mechanism to develop programs. grink tea 2 apple is my favorite food. 3 Football game is not use feet only. # 在第二行后新增三行 [root@CentOS Desktop]# nl regular_express.txt | sed '2a drink rea or ......\ dreak beer\ dreak coffee?' 1 "Open Source" is a good mechanism to develop programs. 2 apple is my favorite food. drink rea or ...... dreak beer dreak coffee? 3 Football game is not use feet only. 4 this dress doesn't fit me. # 必须要有\来转义回车键 # 将2-5行的内容替换(只一遍) [root@CentOS Desktop]# nl regular_express.txt | sed '2,5c No 2-5 number' 1 "Open Source" is a good mechanism to develop programs. No 2-5 number 6 GNU is free air not free beer. # 重复显示5-7行 [root@CentOS Desktop]# nl regular_express.txt | sed '5,7p' 1 "Open Source" is a good mechanism to develop programs. 2 apple is my favorite food. 3 Football game is not use feet only. 4 this dress doesn't fit me. 5 However, this dress is about $ 3183 dollars. 5 However, this dress is about $ 3183 dollars. 6 GNU is free air not free beer. 6 GNU is free air not free beer. 7 Her hair is very beauty. 7 Her hair is very beauty. 8 I can't finish the test. # 显示第5-7行 [root@CentOS Desktop]# nl regular_express.txt | sed -n '5,7p' 5 However, this dress is about $ 3183 dollars. 6 GNU is free air not free beer. 7 Her hair is very beauty.
sed的替换功能
格式:
s/旧字符串/新字符串/g’回顾: .*:任意一个任意字符 *:重复任意次前面的字符 .:任意单个字符 ^:行首 $:行尾
# 查看IP [root@CentOS Desktop]# ifconfig eth1 Link encap:Ethernet HWaddr 00:0C:29:36:97:22 inet addr:192.168.0.209 Bcast:192.168.0.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fe36:9722/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:80045 errors:0 dropped:0 overruns:0 frame:0 TX packets:38016 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:83124783 (79.2 MiB) TX bytes:2972269 (2.8 MiB) Interrupt:19 Base address:0x2024 # 选出IP所在行 inet addr:192.168.0.209 Bcast:192.168.0.255 Mask:255.255.255.0 # 将IP前面的部分删除 [root@CentOS Desktop]# ifconfig eth1 | grep 'inet addr' | sed 's/^.*addr://g' 192.168.0.209 Bcast:192.168.0.255 Mask:255.255.255.0 # 将IP后面的部分删除 [root@CentOS Desktop]# ifconfig eth1 | grep 'inet addr' | sed 's/Bcast.*$//g' inet addr:192.168.0.209
# 找出MAN所在行 [root@CentOS ~]# cat /etc/man.config | grep 'MAN' # when MANPATH contains an empty substring), to find out where the cat # MANBIN pathname # MANPATH manpath_element [corresponding_catdir] # MANPATH_MAP path_element manpath_element # MANBIN /usr/local/bin/man # Every automatically generated MANPATH includes these fields # 承上,删除批注后的数据(批注后的数据会变成空白行) [root@CentOS ~]# cat /etc/man.config | grep 'MAN' | sed 's/#.*$//g' # 承上,删掉空白行 [root@CentOS ~]# cat /etc/man.config | grep 'MAN' | sed 's/#.*$//g' | sed '/^$/d'
# 直接修改文件,并不显示,参数:sed -i # 将文末.$替换成! [root@CentOS Desktop]# sed -i 's/\.$/\!/g' regular_express.txt [root@CentOS Desktop]# cat regular_express.txt "Open Source" is a good mechanism to develop programs! apple is my favorite food! Football game is not use feet only! # 在最后一行新加一行 [root@CentOS Desktop]# sed -i '$a # This is a test' regular_express.txt [root@CentOS Desktop]# cat regular_express.txt ...... ...... # This is a test
扩展正则表达式
# 去除空白行与行首为 # 的行列(三个相同) [root@CentOS Desktop]# grep -v '^$' regular_express.txt | grep -v '^#' [root@CentOS Desktop]# egrep -v '^$|^#' regular_express.txt [root@CentOS Desktop]# grep -E -v '^$|^#' regular_express.txt
# 基础正则表达式 .:一个任意字符 *:为空或任意一个前面的字符 ^:在[]中取反 []:选项 # 扩展正则表达式 +:任意一个或一个以上字符 ?:为空或前一个字符 |:或者 ():一组 ()+:重复多个相同的组 # !在正则表达式中并不是特殊字符 # 查找含有!和>的行 [root@CentOS Desktop]# grep -n '[!>]' regular_express.txt
格式化打印
参数:
关于格式方面的几个特殊样式:
\a 警告声音输出
\b 倒退键(backspace)
\f 清除屏幕 (form feed)
\n 输出新的一行
\r 亦即 Enter 按键
\t 水平的 [tab] 按键
\v 垂直的 [tab] 按键
\xNN NN 为两位数的数字,可以转换数字成为字符。
关于 C 程序语言内,常见的变量格式
%ns 那个 n 是数字, s 代表 string ,亦即多少个字符;
%ni 那个 n 是数字, i 代表 integer ,亦即多少整数码数;
%N.nf 那个 n 与 N 都是数字, f 代表 floating (浮点),如果有小数码数,
假设我共要十个位数,但小数点有两位,即为 %10.2f
# 打印上头数据文件内容 [root@CentOS Desktop]# printf '%s\t %s\t %s\t %s\t %s\t %s\t \n' $( cat printf.txt ) Name Chinese English Math Average DmTsai 80 60 92 77.33 VBird 75 55 80 70.00 Ken 60 90 70 73.33 # 将上述数据关于第二行后,分别以字符串、整数、小数点来显示 [root@CentOS Desktop]# printf '%10s %5i %5i %5i %8.2f \n' $( cat printf.txt | grep -v Name) DmTsai 80 60 92 77.33 VBird 75 55 80 70.00 Ken 60 90 70 73.33 # $和()中间没有空格 # %10s:十位字符串 # 5i:5位整数 # 8.2f:共八位,2个小数点的浮点数
awk:好用的数据处理工具:将一行分成数个字段
awk 主要是处理“每一行的字段内的数据”,而默认的“字段的分隔符号为 “空白键” 或 “[tab]键”[root@CentOS Desktop]# last -n 5 root pts/1 192.168.1.107 Fri Mar 17 22:25 still logged in kevin pts/2 192.168.0.203 Fri Mar 17 19:08 still logged in kevin pts/1 192.168.0.203 Fri Mar 17 13:59 - 21:00 (07:01) kevin pts/1 192.168.0.203 Fri Mar 17 13:56 - 13:58 (00:01) kevin pts/3 192.168.0.203 Fri Mar 17 13:56 - 13:56 (00:00) # 取出账号与登陆者的IP,且账号与IP之间以tab键隔开 [root@CentOS Desktop]# last -n 5 | awk '{print $ 1 "\t" $3}' root 192.168.1.107 kevin 192.168.0.203 kevin 192.168.0.203 kevin 192.168.0.203 kevin 192.168.0.203 wtmp Thu # $1 变量名,第一列 # $2 变量名,第二列 # $0 变量名,一整行数据
整个 awk 的处理流程是: 读入第一行,并将第一行的数据填入 $0, $1, $2.... 等变量当中; 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作"; 做完所有的动作与条件类型; 若还有后续的“行”的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。 awk 是“以行为一次处理的单位”, 而“以字段为最小的处理单 位”。
awk自带的变量名:
我们继续以上面 last -n 5 的例子来做说明,如果我想要:
列出每一行的帐号(就是 $1);
列出目前处理的行数(就是 awk 内的 NR 变量)
并且说明,该行有多少字段(就是 awk 内的 NF 变量)
如下:[root@CentOS Desktop]# last -n 5 | awk '{print $1 "\t line:"NR "\t columes:" NF}' root line:1 columes:10 kevin line:2 columes:10 kevin line:3 columes:10 kevin line:4 columes:10 kevin line:5 columes:10 line:6 columes:0 wtmp line:7 columes:7 # NR,NF是awk自身变量,需要大写,不需要$ # awk后所有动作是单引号扩住 # print和printf是双引号括住
awk的逻辑运算符
# passwd中第一个字段为账号,第三个账号为UID,查阅UID小于10以下的数据,并且仅列出账号与第三列 [root@CentOS Desktop]# cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t" $3}' root:x:0:0:root:/root:/bin/bash bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 # 虽然我们定义了 FS=":" 了,但是却仅能在第二行后才开始生效。我们可以预先设置 awk 的变量啊! 利用 BEGIN 这个关键字。这样做: [root@CentOS Desktop]# cat /etc/passwd | awk ' BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}' root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8
# 上述表格计算总额 # 第一行只是说明,所以第一行不要进行加总 (NR==1 时处理); # 第二行以后就会有加总的情况出现 (NR>=2 以后处理) [root@CentOS Desktop]# cat pay.txt | awk 'NR=1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"Total" }; NR>=2{total = $2+$3+$4; printf "%10s %10s %10s %10s %10.2f\n",$1,$2,$3,$4,total}' Name 1st 2st 3st Total VBird 23000 24000 25000 Total DMTsai 21000 20000 23000 Total Ken 43000 42000 41000 Total
diff: 文件比较工具
通常用于比较两个文件的区别以及同一文件的新旧版本
选项与参数:
from-file :一个文件名,作为原始比对文件的文件名;
to-file :一个文件名,作为目的比对文件的文件名;
注意,from-file 或 to-file 可以 - 取代,那个 - 代表“Standard input”之意。
-b :忽略一行当中,仅有多个空白的差异(例如 “about me” 与 “about me” 视为相同
-B :忽略空白行的差异。
-i :忽略大小写的不同。# 假如我们要将 /etc/passwd 处理成为一个新的版本,处理方式为: 将第四行删除,第六行则取代成为“no six line”,新的文件放置到 /tmp/test 里面,那么应该怎么做? [root@CentOS Desktop]# mkdir -p /tmp /test [root@CentOS ~]# cd /tmp/test [root@CentOS test]# cp /etc/passwd passwd.old [root@CentOS test]# cat /etc/passwd | sed -e '4d' -e '6c no six line' > passwd.new # sed -e 直接在命令行编辑 # 4d:删除地行 # 6c:替换第6行 sed 后面如果要接超过两个以上的动作时,每个动作前面得加 -e 才行 # 比较passwd.old和passwd.new [root@CentOS test]# diff passwd.old passwd.new 4d3 #左边第四行被删除(d)掉了,基准是右边的第三行 < adm:x:3:4:adm:/var/adm:/sbin/nologin #被删除的那行内容 6c5 #左边文件的第六行被取代(c)成右边文件的第五行 < sync:x:5:0:sync:/sbin:/bin/sync --- #左边第五行内容 > no six line #右边第六行内容 # 执行等级3与5的启动脚本分别放置到/etc/rc3.d/和/etc/rc5.d/ [root@CentOS test]# diff /etc/rc3.d/ /etc/rc5.d/ Only in /etc/rc3.d/: K30spice-vdagentd Only in /etc/rc5.d/: S70spice-vdagentd
cmp:文件比较工具
diff主要是以“行”为单位比较
cmp 则是以“字节”为单位去比较
参数:
-l :将所有的不同点的字节处都列出来。因为 cmp 默认仅会输出第一个发现的不同点。
# 比较passwd.old和passwd.new
[root@CentOS test]# cmp passwd.old passwd.new
passwd.old passwd.new differ: byte 106, line 4
- patch:文件比较,打补丁
先比较先旧版本的差异,并将差异档制作成为补丁文件,再由补丁
文件更新旧文件”。
参数:
-p :后面可以接“取消几层目录”的意思。
-R :代表还原,将新的文件还原成原来旧的版本。
# 制作passwd.old和passwd.new的补丁文件
[root@CentOS test]# diff -Naur passwd.old passwd.new > passwd.patch
[root@CentOS test]# cat passwd.patch
--- passwd.old 2017-03-17 23:09:44.352605526 +0800
+++ passwd.new 2017-03-17 23:10:23.149940955 +0800
@@ -1,9 +1,8 @@
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
-adm:x:3:4:adm:/var/adm:/sbin/nologin #左侧文件删除
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
-sync:x:5:0:sync:/sbin:/bin/sync #左侧文件删除
+no six line #右侧文件新加入
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
# 更新
[root@CentOS test]# patch -pN < patch_file
# 还原
[root@CentOS test]# patch -R -pN < patch_file
# 将旧的文件更新成为新的内容,就是将passwd.old改成与passwd.new相同
[root@CentOS test]# patch -p0 < passwd.patch
patching file passwd.old
[root@CentOS test]# ll passwd*
-rw-r--r--. 1 root root 2491 3月 17 23:10 passwd.new
-rw-r--r--. 1 root root 2491 3月 17 23:31 passwd.old #相同
-rw-r--r--. 1 root root 480 3月 17 23:26 passwd.patch
[root@CentOS test]# patch -R -p0 < passwd.patch
patching file passwd.old
[root@CentOS test]# ll passwd*
-rw-r--r--. 1 root root 2491 3月 17 23:10 passwd.new
-rw-r--r--. 1 root root 2548 3月 17 23:32 passwd.old #不同
-rw-r--r--. 1 root root 480 3月 17 23:26 passwd.patch
- pr:文件打印
如果我是在
Linux 下面打印纯文本文件呢 可不可以具有标题啊?可不可以加入页码啊?当然可以。使用 pr 就能够达到这个功能了
[root@CentOS test]# pr passwd.old
2017-03-17 23:32 passwd.old 第 1 页
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
.......
.......
.......