正则表达式-awk和sed两个工具的使用

文章介绍了正则表达式的元字符及其在匹配字符串中的作用,同时详细讲解了awk和sed这两个Unix/Linux工具的使用,包括打印指定列、格式化输出、过滤、分隔符指定、正则表达式匹配等功能,并提供了多个实例展示如何处理表格数据和进行文本操作。
摘要由CSDN通过智能技术生成

正则表达式
================================
    1.作用
              用人为规定一些特殊符号表示匹配字符串
              适用场景:模糊匹配字符串
       元字符:  正则表达式中具有特殊含义的字符,叫做元字符
    2.常用的元字符
              grep "^he"  1.txt -Hn   //匹配行首he
              (1) 逻辑或需要转义
                         grep "he\|ha"  1.txt  -Hn
              (2)不出现,或者出现一次  ?需要转义
                         grep "hel\?o"  1.txt  -Hn
                                     问号需要转义
                                     l\?表示l不出现,或者l出现一次
              (3)出现一次,后者出现多次   +需要转义
                        grep "hel\+o"  1.txt  -Hn
              (4)指定重复次数  {}左右两边需要转义
                        grep "hel\{2,4\}o"  1.txt  -Hn


awk和sed两个工具的使用
================================
    1.awk处理表格中列
             安装awk:  sudo  apt-get install  awk
             作用:主要用于统计表格中的信息,打印列
             注意的要点:
                        第一:  搜索字符串
                                awk  '$0~/你要匹配的字符串/ {print}'    要搜索的文件名
                               
                                .* 表示匹配任意长度的字符串
    2.sed也能处理表格数据
              安装sed:  sudo  apt-get install  sed
              作用:字符串的增删改查都可以
              命令总结:
                       第一:替换
                             sed  "s/旧字符串/新的字符串/"   people.txt

awk编程入门

测试文档:(grade.txt)

M.Tansley 05/2013 48311 Green 8 90

J.Lulu 04/2012 48317 green 12 88

P.bunny 02/2013 48 Yellow 9 70

J.Troll 09/2013 4842 Brown-3 11 95

L.Tansley 05/2013 4712 Brown-2 10 85

Vincent 07/2012 4712 Brown 13 87

1,打印指定列(例如名字和年龄)

awk  '{print $1,$5}'  grade.txt

注意:其中单引号中的被大括号括着的就是awk的语句,只能被单引号包含。

其中的$1..$n表示第几例。$0表示整个行。

注意:awk的工作次序是:首先读取grade.txt文件一个记录(即一行),然后根据单引号内部的指令工作,完了之后继续读下一行,以此类推。每读一行都会将单引号里面的语句从头到尾地应用到那一行中去。

2,格式化输出(和C语言一样一样的)

awk  '{printf"%-10s:%-d\n", $1,$5}'  grade.txt

3,过滤

awk  '$5==11 && $6>=90 {print $0}'  grade.txt

意思是==>打印出年龄等于11岁且分数大于90分的孩子的信息

4,打印表头,引入内建变量NR

awk  'NR==1 || $6>=90 {print}'  grade.txt

注意:NR是一个所谓的内建变量,表示已经读出的记录数(即行号)

其它有用的内建变量是:

$0

当前记录(这个变量中存放着整个行的内容)

$1~$n

当前记录的第n个字段,字段间由FS分隔

FS

输入字段分隔符 默认是空格或Tab

NF

当前记录中的字段个数,就是有多少列

NR

行号,从1开始,如果有多个文件这个值将不断累加。

FNR 

  

 当前记录数,与NR不同的是,这个值会是各个文件自己的行号

 RS  

  

 输入的记录分隔符, 默认为换行符

 OFS  

  

 输出字段分隔符, 默认也是空格

 ORS  

  

 输出的记录分隔符,默认为换行符

 FILENAME  

  

 当前输入文件的名字

5,指定分隔符

awk  ‘BEGIN{FS=”:”} {print $1}’  /etc/passwd

注意:BEGIN意味着紧跟在它后面的语句{FS=:}会在awk读取第一行之前处理。

上面的语句等价于

awk  -F:  ‘{print $1}’  /etc/passwd

如果有多个分隔符,则可以写成

awk  -F’[\t;:]’  ‘{print $1}’  /etc/passwd

6,使用正则表达式匹配字符串

awk  '$0~/Brown.*/ {print}'  grade.txt  意思是==>将所有包含Brown的行打印出来

注意:波浪号~后面紧跟着一对正斜杠,表示所指定的域(这里是$0)要匹配的规则

7,使用模式取反的例子

awk  '$0!~/Brown.*/ {print}'  grade.txt  意思是==>将所有不包含Brown的行打印出来

拆分文件

8,将各年龄段的孩子的信息分别存放在各个文件中

awk 'NR!=1 {print > $5}' grade.txt

意思是==>表头不处理,后面的每一行,都将被重定位到以第5个域(年龄)命名的文件中去。

也可以将指定的域重定位到相应的文件

awk 'NR!=1 {print $1, $6 > $5}' grade.txt

意思是==> 不处理表头,将每一行中的姓名和分数重定位到与其年龄相应的文件中去。

9,再复杂一点,按级别将信息分成三个文件:

awk 'NR!=1 {if($4~/Brown.*|Black/) print > "high.txt";

   else if($4~/Yellow|[Gg]reen/) print > "midle.txt";

   else print > "low.txt"}' grade.txt

意思是==> 如果记录中的第4个域($4)匹配Brown.*或者Black,就将该记录重定位到文件high.txt中,如果匹配Yellow或者[Gg]reen,就重定位到midle.txt中,否则统统重定位到low.txt中。

统计

10,将所有孩子的分数累积起来并打印出来

awk  '{sum+=$6} END{print sum}'  grade.txt

注意:END表示->紧跟其后的语句只会在awk处理完所有行之后才被执行。

11,统计各个级别的人数

awk 'NR!=1 {a[$4]++;} END{for(i in a) print i","a[i];}' grade.txt

注意:$4是级别名称,例如Yellow、Brown等,a是一个以这些级别为下标的数组,其值从零开始计算。i就是Yellow、Brown等   a[i]是对应有几个Yellow、Brown 中间用逗号隔开

awk脚本

12,想象我现在要打印出整个班级的所有孩子的信息,而且在最前面把表头也打印出来,而且下面要打印一行“===========”来跟具体内容加以划分。并且在最后一行,统计孩子们的平均年龄以及平均分数。将awk语句组织成脚本,如下:

#!/usr/bin/awk -f

#/usr/bin/awk指定脚本解释器的位置,-f表示运行该脚本需要指定一个文件作为输入

BEGIN{ #awk开始运行之前的准备工作(定义了两个变量),此左花括号必须紧跟BEGIN

age = 0

score = 0

}

{

if(NR==1) #打印表头已经分割线

{

print $0

printf "==============================" #由于是printf,没有\n就不换行

print  "==============================" #由于是print,会自动换行

}

else

{

age+=$5

score+=$6

print $0

}

}

END{ #awk处理完所有的记录之后,END才开始运行

printf "=============================="

print  "=============================="

print "Average:\t\t\t\t\t" age/NR  ",\t" score/NR

}

关于sed

测试文档:(people.txt)
Jack    is 18-year old, he comes from US.
Mike    is 16-year old, he comes from Canada.
Chen    is 21-year old, he comes from China.
Lau    is 18-year old, he comes from HongKong.
Michael    is 20-year old, he comes from UK.
Phoebe    is 18-year old, she comes from Australie.

1,替换:
例如,将"-year"改成" years":
sed  "s/-year/years/" people.txt 

2,指定某些行替换:
例如,将第2行的"-year"改成" years":
sed  "2s/-year/years/" people.txt

再如,将第2至5行的"-year"改成" years":
sed  "2,5s/-year/years/" people.txt

3,直接通过sed修改原文,加选项 -i:
sed  -i "2s/-year/years/" people.txt
注意:sed缺省状态下不会修改原文

4,替换每一行中的所有的小写s成大写S:
sed  "s/s/S/g" people.txt
注意:g的意思是一行中所有的匹配项,否则缺省只会匹配第一个s

5,替换每一行中的第2个小写s成大写S:
sed  "s/s/S/2" people.txt

6,替换每一行中的第2个以后的小写s成大写S:
sed  "s/s/S/2g" people.txt

多个匹配
7,将"-year"改成" years",并且将第3行以后的最后一个任意字符去掉:
sed 's/-year/ years/; 3,$s/.$//' people.txt 
以上命令等价于:
sed -e 's/-year/ years/' -e '3,$s/.$//' people.txt
注意:在单引号里面,元义字符可以直接使用,如果要去掉元义则要在前面加\ ; 在双引号里面,sed的命令要使用元义,则需要加\ , 而命令的正则表达式要使用元义直接使用就行。


8,将&代替被匹配的变量:
sed "s/is/[&]/" people.txt
意思是==>:将文本中每一行出现的第一个is的左右两边加上[ ]

9,如果使用正则表达式匹配项的时候使用了圆括号括了起来,那么可以用\1,\2,\3……等来表示这些项:
sed "s/\(^.*\)\tis.*from \(.*\)./\1\t:\2/g" people.txt
分解一下:
1,其中加粗的\(^.*\)\tis.*from \(.*\).是正则表达式,简化一下是(^.*)\tis.*from (.*). 在这个表达式中,制表符\t前面的匹配项可以被记为\1,from后面的匹配项可以被记为\2
2,后面加下划线的\1\t:\2部分是替换的字符串,也就是只打印匹配出来的名字和国籍,中间用制表符和冒号隔开。

10,提前预读多一行缓冲来进行匹配:
sed 'N;s/is/IS/' people.txt
注意:由于替换只会针对第一个出现的单词is,而通过N又多读了一行,因此这个命令的结果是只会替换奇数行。

11,在指定行的前面插入(i)或者后面插入(a)一些信息:
sed '3i abcd' people.txt  意思是==>在第3行的前面插入abcd
sed '2a abcd' people.txt  意思是==>在第2行的后面插入abcd
sed '1,4a abcd' people.txt  意思是==>在第1至4行的后面分别插入abcd
sed '/US/a abcd' people.txt  意思是==>在匹配US的行的后面插入abcd

12,将指定的行替换成其他信息:
sed "2c ok" people.txt  意思是==>将第2行替换成ok

13,将指定的行删除掉:
sed ‘2d’ people.txt  意思是==>将第2行给删掉
sed ‘/US/d’ people.txt  意思是==>将匹配/US/的所有行给删掉
sed  '/\<he\>/d' people.txt 意思是==>将匹配he的所有行给删掉,注意:之所以要用<>将he给括起来,是因为不想匹配she,当然,<>需要转义,写成\<\>

14,打印指定匹配的行,用命令p:
sed '/Chen/p' people.txt  -n  意思是==>打印匹配Chen的行
sed '/Chen/, /Lau/p' people.txt  -n  意思是==>打印匹配Chen或者Lau的行
sed '3,/UK/p' people.txt  -n  意思是==>从第3行开始打印,直到匹配UK为止
sed '/UK/,6p' people.txt  -n  意思是==>从匹配UK的行开始打印,直到第6行为止

15,使用相对位置:
sed '/US/, +2p' people.txt -n  意思是==>打印匹配US的行,并打印其后的2行。

16,执行多个命令:
sed '{/he/{/18/p}}' people.txt -n 意思是==>匹配所有/he/的行之后,再匹配/18/的行,然后打印出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hqb_newfarmer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值