[9] 正则表达式

[9] 正则表达式

正则表达式,又称规则表达式。(英语:Regular Expression,正则就是一串有规律的字符串。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。

9.1 grep 命令详解

  • 基本语法和参数
语法: grep [-cinvABC] '过滤关键词' 文件名

-c :打印符合要求的行数  只显示符合关键词的总行数,不显示行的内容
-n :在输出符合要求的行的同时连同行号一起输出
-i :不区分搜索大小写
-v :打印不符合要求的行 
-r : 会把目录下面所有的文件全部遍历,不加r,只能针对文件搜索,而不是整个目录下的文件内容。遍历文件,同时也会把匹配到的关键字所在的文件路径列出来,如果不想列出文件路径,使用-h参数就可以了
-A :后跟一个数字(有无空格都可以),例如 –A2则表示打印符合要求的行以及下面两行 
-B :后跟一个数字,例如 –B2 则表示打印符合要求的行以及上面两行 
-C :后跟一个数字,例如 –C2 则表示打印符合要求的行以及上下各两行

--color: 把匹配到的关键词用红色标识  永久显示,把设置别名的命令写到.bashrc文件中,source .bashrc生效环境变量

. 表示任意一个字符; 
* 表示零个或多个(任意个)前面的字符; 
.* 表示零个或多个任意字符,空行也包含在内
  • grep/egrep示例

过滤出带有某个关键词的行并输出行号

[root@localhost ~]# grep -n 'root' 1.txt 

过滤出不带有某个关键词的行并输出行号

[root@localhost ~]# grep -n -v 'root' 1.txt 

过滤出所有包含数字的行

[root@localhost ~]# grep '[0-9]' 1.txt

过滤出所有不包含数字的行

[root@localhost ~]# grep -v '[0-9]' 1.txt 

过滤出包含root的行以及下面一行

[root@localhost ~]# grep -A1 'root' 1.txt

过滤出包含root的行以及上面一行

[root@localhost ~]# grep -B1 'root' 1.txt

过滤出包含root的行以及上下各一行

[root@localhost ~]# grep -C1 'root' 1.txt

去除所有以’#’开头的行

[root@localhost ~]# grep -v '^#' 1.txt 
[root@localhost ~]# grep  '^[#]' 1.txt

去除所有空行和以#开头的行

[root@localhost ~]# grep -v '^$' 1.txt|grep -v '^#' 

过滤出以英文字母开头的行

[root@localhost ~]# grep '^[a-zA-Z]' 1.txt

过滤出以非数字开头的行

[root@localhost ~]# grep '^[^0-9]' 1.txt 
说明: 在[]里面加^表示取非
grep '^[^0-9]' 1.txt  过滤出非数字开头的行,不包括数字、空行,包括特殊字符,字母,空格 
grep -v '^[0-9]' 1.txt 过滤出非数字开头的行,不包括数字,包括空行、特殊字符、字母、空格

过滤任意一个或多个字符

[root@localhost ~]# grep 'r.o' 1.txt
[root@localhost ~]# grep 'r*t' 1.txt
[root@localhost ~]# grep 'r.*t' 1.txt

指定过滤字符次数

[root@localhost ~]# grep 'o\{2\}' 1.txt
grep 'o\{2\}' 1.txt == grep -E '(oo)' 1.txt

把一个目录下,过滤所有*.php文档中含有eval的行

[root@localhost ~]# grep -r --include="*.php" 'eval' /data/
  • egrep 命令详解

    egrep执行效果与”grep-E”相似,使用的语法及参数可参照grep指令,与grep的不同点在于解读字符串的方法。


指定过滤字符次数
[root@localhost ~]# egrep 'o{2}' 1.txt

匹配1个或1个以上+前面的字符

[root@localhost ~]# egrep 'o+' 1.txt

匹配0个或者1个?前面字符

[root@localhost ~]# egrep 'oo?' 1.txt

匹配roo或者nologin

[root@localhost ~]# egrep 'roo|nologin' 1.txt

匹配1个或者多个 ‘oo’

[root@localhost ~]# egrep '(oo)+' 1.txt
[root@localhost ~]# egrep '(oo){2}' 1.txt

用括号表示一个整体,下面例子会匹配roo或者ato

[root@localhost ~]# egrep 'r(oo)|(at)o' 1.txt 

9.2 sed 命令详解

sed 可以过滤、替换、删除、调换

-r                        对特殊字符进行脱意,等同于使用\
-n                         只打印符合规范的行
/关键字/p                   搜索打印关键字行
/关键字/d                   搜索删除关键字行
s/关键字/替换内容/g         文本替换
  • sed 示例

打印指定行

[root@localhost ~]# sed '10'p -n 1.txt 
[root@localhost ~]# sed '1,4'p -n 1.txt 
[root@localhost ~]# sed '5,$'p -n 1.txt
说明: 这里的p是print的意思,加上-n后就可以只打印符合规则的行,如果不加则会把1.txt从头到尾打印一遍。

打印包含某个字符串的行

[root@localhost ~]# sed -n '/root/'p 1.txt 
可以使用 ^ . * $等特殊符号 
[root@localhost ~]# sed -n '/ro.t/'p 1.txt 
[root@localhost ~]# sed -n '/^roo/'p 1.txt
sed跟grep一样,不识别+|{}()等符号,需要借助脱义符号\或者使用选项-r 
[root@localhost ~]# sed -nr '/ro+/'p 1.txt 
[root@localhost ~]# sed -n '/ro\+/'p 1.txt 上面两个命令效果是一样的。

-e 可以实现同时进行多个任务

[root@localhost ~]# sed -e '/root/p' -e '/body/p' -n 1.txt 
也可以用;实现 
[root@localhost ~]# sed '/root/p; /body/p' -n 1.txt

删除指定行

[root@localhost ~]# sed '/root/d' 1.txt
sed '1d' 1.txt          删除第一行
sed '1,10d' 1.txt       删除110行
说明:'/root/d' 删除包含root的行

删除所有数字

[root@localhost ~]# sed 's/[0-9]//g' 1.txt 
说明: 其实就是把所有数字替换为空字符,g的作用是替换一行中出现的所有字符

文本替换

[root@localhost ~]# sed '1,12s/root/toor/g' 1.txt

[root@localhost ~]# sed -r '1,12s/ro+/toor/g' 1.txt

删除所有非数字

[root@localhost ~]# sed 's/[^0-9]//g' 1.txt

调换两个字符串位置

[root@localhost ~]# head -n2 1.txt |sed -r 's/(root)(.*)(bash)/\3\2\1/' 
说明:在sed中可以用()去表示一个整体,本例中把root和bash调换位置,后面的\1\2\3分别表示第一个小括号里面的,第二个小括号里面的以及第三个小括号里面的内容。

-i 选项可以直接修改文件内容

[root@localhost ~]# sed -i 's/ot/to/g' 1.txt

I参数匹配关键词时不区分大小写

[root@localhost ~]# sed -n '/root/'Ip 1.txt
grep使用-i选项不区分大小写

9.3 awk 命令详解

可以截取、过滤、数学计算

  • awk示例

截取文档中的某段

[root@localhost ~]# awk -F ':' '{print $1}' 1.txt ==cut -d: -f1 1.txt
说明: -F指定分隔符号为:,若要截取所有的段,使用$0
也可以使用自定义字符连接每个段 
[root@localhost ~]# awk -F':' '{print $1"#"$2"#"$3"#"$4}' 1.txt 
或者使用awk内部变量OFS,格式如下: 
# awk -F ':' '{OFS="#"} {print $1,$2,$3,$4}' 1.txt

匹配字符或字符串

[root@localhost ~]# awk '/oo/' 1.txt 

针对某个段匹配

[root@localhost ~]# awk -F ':' '$1 ~/oo/' 1.txt 

多次匹配

[root@localhost ~]# awk -F ':' '/root/ {print $1,$3}; $1 ~/test/; $3 ~/20/' 1.txt

条件操作符[==]、[>]、[<]、[!=]、[>=]、[<=]

第三段为0 
[root@localhost ~]# awk -F ':' '$3=="0"' 1.txt
第三段大于等于500 
[root@localhost ~]# awk -F ':' '$3>=500' 1.txt
说明:当比较数字时,不能加双引号,如果写成$3>="500"就不符合我们的需求了。
第七段不是'/sbin/nologin' 
[root@localhost ~]# awk -F ':' '$7!="/sbin/nologin"' 1.txt
第三段小于第四段 
[root@localhost ~]# awk -F ':' '$3<$4' 1.txt ;
第三段大于5,并且第三段小于7 
[root@localhost ~]# awk -F ':' '$3>5 && $3<7' 1.txt
第三段大于5或者第七段为'/bin/bash' 
[root@localhost ~]# awk -F ':' '$3>"5" || $7=="/bin/bash"' 1.txt

awk内置变量 NF(段数fields) NR(行数records)

[root@localhost ~]# head -n3 1.txt | awk -F ':' '{print NF}' 
[root@localhost ~]# head -n3 1.txt | awk -F ':' '{print $NF}' 打印最后一段
[root@localhost ~]# head -n3 1.txt | awk -F ':' '{print NR}'
awk -F ':' '{print NF "#" NR}' passwd
打印20行以后的行 
[root@localhost ~]# awk 'NR>20' 1.txt 
打印20行以后并且第一段包含'ssh'的行 
[root@localhost ~]# awk -F ':' 'NR>20 && $1 ~ /ssh/' 1.txt 
更改某个段的值 
[root@localhost ~]# awk -F ':' '$1="root"' 1.txt

数学计算, 把第三段和第四段值相加,并赋予第七段

[root@localhost ~]# awk -F ':' '{$7=$3+$4; print $0}' 1.txt 
但是这样的话,相当于改变了原来文本的结构,所以print $0的时候就不再有分隔符显示。如果想显示分隔符需要借助OFS 
[root@localhost ~]# awk -F ':' '{OFS=":"} {$7=$3+$4; print $0}' 1.txt

计算第三段的总和

[root@localhost ~]# awk -F ':' '{(tot=tot+$3)}; END {print tot}' 1.txt 

awk中也可以使用if关键词

[root@localhost ~]# awk -F ':' '{if ($1=="root") print $0}' 1.txt
[root@localhost ~]# awk -F ':' '{if ($1~/root/) print $0}'   $0代表整行

扩展

[root@localhost ~]# sed -n '/ens33/,/TX/p' 1.txt 
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.11  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::e573:6122:85e7:b1a9  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:a0:8e:5c  txqueuelen 1000  (Ethernet)
        RX packets 716  bytes 68017 (66.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 570  bytes 65787 (64.2 KiB)

sed中,使用\u表示大写,\l表示小写

1. 把每个单词的第一个小写字母变大写:
sed 's/\b[a-z]/\u&/g' filename

2. 把所有小写变大写:
sed 's/[a-z]/\u&/g' filename

3. 大写变小写:
sed 's/[A-Z]/\l&/g' filename
[root@localhost ~]# sed  -n "s/\(^a.*\)/\1 123/p" passwd 
adm:x:3:4:adm:/var/adm:/sbin/nologin 123
abrt:x:173:173::/etc/abrt:/sbin/nologin 123
[root@test200 ~]# cat test
a
b
c
d
e
f
[root@test200 ~]# sed '/c/{p;:a;N;$!ba;d}' test
a
b
c

定义一个标签a,匹配c,然后N把下一行加到模式空间里,匹配最后一行时,才退出标签循环,然后命令d,把这个模式空间里的内容全部清除。

if 匹配"c"
:a
追加下一行
if 不匹配"$"
goto a
最后退出循环,d命令删除
[root@localhost ~]# sed  -n '1,100{/abc/p}'  1.txt
A=44echo "ABCD" | awk -v GET_A=$A ’{print GET_A}’
说明:-v选项用于定义参数,这里表示将变量A的值赋予GET_A。
有多少个变量需要赋值,就需要多少个-v选项。与之等价的:应用于脚本中:

#! /bin/bash
sort -n filename |awk -F ':' '{print $1}'|uniq >id.txt
for id in `cat id.txt`; do
        echo "[$id]"
        awk -v id2=$id -F ':' '$1==id2 {print $2}' filename  // 另外的方式为: awk -F ':' '$1=="'id'" {print $2}' filename  
done
附件:
cat filename
1111111:13443253456
2222222:13211222122
1111111:13643543544
3333333:12341243123
2222222:12123123123
运行脚本后结果为:
[1111111]
13443253456
13643543544
[2222222]
13211222122
12123123123
[3333333]
12341243123
把两个文件中,第一列相同的行合并到同一行中

awk 'NR==FNR{a[$1]=$2}NR>FNR{print $0,a[$1]}'  1.txt  2.txt

解释:NR表示读取的行数,FNR表示读取的当前行数
所以其实NR==FNR 就表示读取2.txt的时候。 同理NR>FNR表示读取1.txt的时候
数组a其实就相当于一个map
a=`cat file`;echo $a 
awk '{printf("%s ",$0)}' file   // %s 后记得要有一空格,否则出来就是完全连在一起的,中间连空格都没有
cat file |xargs
passwd文件中把所有www替换为abc
awk 'gsub(/www/,"abc")' /etc/passwd

替换$1中的www为abc
awk -F ':' 'gsub(/www/,"abc",$1) {print $0}' /etc/passwd
for j in `seq 0 20`; do
        let x=100*$j
        let y=$x+1
        let z=$x+100
        for i in `seq $y $z` ; do
                awk  -v a=$i '{printf $a " "}' example.txt >>/tmp/test.txt
                echo " " >>/tmp/test.txt
        done
done
找出文件(filename)中包含123或者包含abc的行
grep -E '123|abc' filename

用egrep同样可以实现
egrep '123|abc' filename 

awk 的实现方式
awk '/123|abc/'  filename
用awk编写生成以下结构文件的程序。( 最后列使用现在的时间,时间格式为YYYYMMDDHHMISS)  各列的值应如下所示,每增加一行便加1,共500万行。

1,1,0000000001,0000000001,0000000001,0000000001,0000000001,0000000001,2005100110101
2,2,0000000002,0000000002,0000000002,0000000002,0000000002,0000000002,2005100110101

#! /bin/bash

for i in `seq 1 5000000`; do
    n=`echo "$i"|awk '{print length($0)}'`
    export m=$[10-$n]
    export o=`perl -e '$a='0'; $b=$a x $ENV{"m"}; print $b;'`
    export j=$i
    p=`perl -e '$c=$ENV{"o"}.$ENV{"j"}; print $c;'`
    echo "$i,$i,$p,$p,$p,$p,$p,$p,`date +%Y%m%d%H%M%S`"
done


awk 实现方式
awk 'BEGIN{for(i=1;i<=10;i++)printf("%d,%d,%010d,%010d,%010d,%010d,%010d,%010d,%d\n",i,i,i,i,i,i,i,i,strftime("%Y%m%d%H%M"))}'
awk '{print "This is a '"'"'"$1} filename 
解释一下:在awk中使用脱义字符\是起不到作用的,如果想打印特殊字符,只能使用'""' 这样的组合才可以。
这里自左至右为单引号 双引号 双引号 单引号其中两个单引号为一对,两个双引号为一对。想脱义$那就是'"$"' 脱义单引号那就是 '"'"'
paste  filename1  filename2 

-d 指定连接符
paste -d '+'  a.txt b.txt
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值