linux正则表达式工具grep、sed、awk的使用及案例

目录

特殊字符

命令行工具:grep、sed、awk

grep

语法

案例

sed

语法

案例

awk

语法

案例


特殊字符

元字符含义案例
.匹配任意单个字符

a.b可以匹配字符串"abc"、"aac"、"acc"等

^匹配字符串的开头^abc可以匹配以abc开头的字符串,如"abcdef"
$匹配字符串的结尾$abc可以匹配以abc为结尾的字符串,如"123abc"
*匹配前面的字符零次或多次

1、*.txt表示匹配.txt为结尾的文件

2、a*b 可以匹配"aab"、 "aabb"、 "asdfb" 等等

+匹配前面的字符一次或多次匹配连续的数字:echo "123456" | grep -E "[0-9]+"
?匹配前面的字符零次或一次

1、colou?r 匹配color或colour

2、.?匹配零个或一个任意字符

{n}匹配前面的字符恰好n次

1、a{3} 表示连续出现3个a,即aaa

2、[0-9]{2} 表示连续出现两个数字

{n,}匹配前面的字符至少n次

1、a{2,}表示前面的字符a必须出现2次

2、[0-9]{3,}表示匹配至少三位数

{n,m}匹配前面的字符至少n次,但不超过m次b{2,3}a表示前面的字符"b"必须重复出现2到3次,并且后面紧跟着字符"a"
[ ]

1、匹配方括号内的任意一个字符

2、方括号中可以使用反向引用符(^)表示匹配除指定字符以外的任何字符。

3、方括号也可以包含一些转义字符

1、[abc]表示匹配a,b,c中的任意一个

2、[a-z]表示匹配小写字母a到z中的任意一个

3、[0-9]表示匹配数字0到9中的任意一个

4、[^abc]表示匹配除了字符a、b、c以外的任意字符

5、[\t]表示匹配制表符

|匹配两个或多个分支之一pattern1|pattern2表示匹配模式pattern1或pattern2。
()标记一个子表达式的开始和结束位置

可以分组和控制优先级

命令行工具:grep、sed、awk

这三个工具通常可以结合管道 | 和重定向符号 >>> 等一起使用,组合出强大的文本处理能力。

grep

grep是一种文本搜索工具,它可以在文件中查找匹配某个模式的行,并将匹配的行输出到屏幕上。grep支持正则表达式,可以行进高级搜索。

语法

grep [options] pattern [files]

即:grep [选项] [字符串或正则表达式] [文件名]

常用选项:

-i:忽略大小写进行匹配

-v:反向查找,只打印不匹配的行

-n:显示匹配行的行号

-r:递归查找子目录中的文件

-l:只打印匹配的文件名

-c:只打印匹配的行数

-o:只显示匹配到的部分

-E:使用正则表达式

pattern:

\b为单词锁定符,如 '\bhello' 从左往右匹配hello,如 '123' 从右往左匹配123,如 '/b123/b' 只匹配123

一些字符在pattern中有特殊含义,若想匹配需要用到转义字符“\”。例如:grep '\$' test.txt 即查找'$'。特殊字符有 \\  \  '  ''  $  |  ^等

细节:

1、默认情况下,grep命令区分大小写。忽略大小写可以用-i选项

2、若搜索字符串包含空格需要用引号将其括起

3、如果使用扩展正则表达式,特殊符号是不用使用转义字符\

        例:grep "2\{1,3\}" file.txt        (需要转义字符)

                grep -E "2{1,3}" file.txt        (正则表达式,不需要转义字符)

案例

1、匹配test.txt文件中的字符串"hello"。

grep hello test.txt

2、匹配字符串"abcabcabc"中的所有"ab"。

echo abcabcabc | grep "\(ab\)\{1\}"

"\"表示转义字符,{1}表示ab恰好1次

3、找出ens33的ip地址、子网掩码、广播地址,即下图红框部分。

ifconfig ens33 | grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"

[0-9]表示0到9的数字,{1,3}表示0到9的数字最少出现1次,最多出现3次,\.表示字符 “ . ”

4、test.txt文件中有三行字符串,“123456789@qq.com”、“1234567890@123.com”、“123qwedsf”,筛选出带有“@”的邮箱地址。

cat test.txt | grep -E "[0-9a-z]+@[0-9a-z]+\.com"

[0-9a-z]表示可以包含所有的数字所有的小写字母

5、查找“ifconfig ens33”命令结果中的1-255之间的整数

ifconfig ens33 | grep -Eo "\b([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b"

其中“|”表示或的意思。1-255可以分为几种情况讨论,[1-9]表示个位数,[1-9][0-9]表示十位数,1[0-9][0-9]表示100~199的数,2[0-4][0-9]表示200~249的数,25[0-5]表示250~255的数。

6、显示/etc/passwd当中,所有已sh为结尾的行

cat /etc/passwd | grep -E "sh$"

7、匹配/etc/inittab中的所有以s开头,而且d为结尾的单词

cat /etc/inittab | grep '\bs[a-z]*d\b'

用单词锁定符“\b”

8、已知test.txt文件中有三行:“987-123-4567”、“987 456-1230”、“(123) 456-7890”。用grep全部筛选出来

cat test.txt | grep -E "^(\([0-9]+\)|[0-9]+)[ -]?[0-9]+[- ]?[0-9]+"

 [0-9]表示任意数字,\([0-9]+\)表示括号加任意数字,即“(任意数字)”。^(\([0-9]+\)|[0-9]+)表示“ [0-9] ”或“([0-9])”为开头。[ -]?表示空格或 “-” 的其中的一个。

9、高亮显示/etc/passwd文件中的冒号,及其两侧的字符

cat /etc//passwd | grep -E ".?:*:.?"

sed

sed是一种流编辑器,它可以从输入流(例如文件或管道)中读取文本,并对其进行操作。sed通常用于对文本进行替换或删除操作,也可以进行插入、追加和编辑等操作。

语法

sed [选项] '动作' 文件

选项参数

-n:禁止自动打印模式空间的内容

-e:允许对输入应用多条 sed 命令。以选项中指定的script来处理输入的文本文件

-f:以选项中指定的script文件来处理输入的文本文件

-i:直接修改文件内容,而不是在标准输出上显示结果。(没有这个选项只是显示而不影响文件)

-h:显示帮助

-v:显示版本信息

-r:表示使用扩展正则表达式

动作:

替换:s/old/new/,用 new 来替换每一行中第一个匹配到的 old。

删除:d,删除指定条件的行

插入:i\text,在指定位置插入文本

打印:p,打印符合条件的行,通常 p 会与参数 sed -n 一起运行

替换标记:g,用于替换所有匹配到的内容

新增:a, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)

取代:c,c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行

示例:

替换文本:sed 's/old/new/g' file.txt

删除匹配行:sed '/pattern/d' file.txt

多个操作组合:sed -e 's/foo/bar/' -e '/pattern/d' file.txt

sed -f 1.txt 2.txt 意思是使用 sed 工具,并且将 1.txt 文件中的命令和正则表达式应用到目标文件 2.txt 上,从而实现修改操作。在执行时,sed 依次读取脚本文件中的每一行,并对目标文件进行修改,最终将修改结果输出到标准输出(终端)上。

需要注意的是,这个命令不会修改原始文件,而是将结果输出到标准输出上。如果想要将结果写回到原始文件中,可以使用 -i 选项

 
案例

1、打印/etc/passwd

sed ' ' /etc/passwd        或        cat /etc/passwd | sed ' '

2、用sed打印test.txt文件

sed -n 'p' test.txt

命令 sed -n 'p' test.txt 将会将文件 test.txt 中的每一行都打印(输出)出来。由于使用了 -n 选项,所以只会显示经过 sed 处理后的结果,不会显示原始文件的内容。这个命令等同于 cat test.txt,因为它只是简单地打印文件的内容而已,没有进行任何修改或过滤操作。

3、打印test.txt文件中包含字母‘o’的行

sed -n '/o/p' test.txt

/o/是一个正则表达式,表示匹配包含字母 "o" 的行

4、打印在文件 /etc/passwd 中查找以 "root" 开头的行

sed -n '/^root/p' /etc/passwd

5、在 /etc/passwd 文件中从第四行开始寻找,一直到第一个以 "bash" 结尾的行,并将这个范围内的行打印出来。

sed -n '4,/bash$/p' /etc/passwd

6、在文件 /etc/passwd 中查找包含连续出现两次或更多次 "99:" 的字符串的行,并将这些符合条件的行打印出来。

sed -r -n '/(99:){2,}/p' /etc/passwd

 /(99:){2,}/ 是一个正则表达式,表示匹配连续出现两次或更多次 "99:" 的字符串。

7、打印/etc/passwd 文件中要么root开头,要么bash结尾的行

sed -r -n '/^root|bash$^C' /etc/passwd

8、删除文件test1.txt所有的行

sed -i 'd' test1.txt

9、删除文件test1.txt的第三行和第七行

sed -i '3d;7d' test1.txt

3d;7d 表示删除第三行到第七行。如果是删除第三行到第七行,则用逗号,sed -i '3d,7d' test1.txt

10、删除空行

sed -i '/^$/d' test1.txt

/^$/ 表示匹配一个空行

11、在文件 test02.txt 的最后一行后面追加文件 test01.txt 的内容

sed '$r test01.txt' test02.txt

$表示最后一行。若想在特定的行下插入,则改为    sed '/特定的行/r test01.txt' test02.txt

r test01.txt是sed的一个命令,用于读取文件 test01.txt 的内容,并将其追加到指定位置。

由于没有加 -i 选项,所以这个命令不会修改原始文件,而是将结果输出到标准输出(终端)。

12、在test.txt文件内新增“123456”字符串

sed '$a 123456' test.txt

13、将字符串 “aaabbbcccddd” 替换成 “cccbbbaaa” 

echo aaabbbcccddd | sed -r 's/(aaa)(bbb)(ccc)(ddd)/\3\2\1/'

s/(aaa)(bbb)(ccc)(ddd)/\3\2\1/ 是替换命令,用于匹配并替换字符串中的内容

(aaa)(bbb)(ccc)(ddd) 是一个正则表达式,用括号分组表示四个部分:aaa、bbb、ccc、ddd

\3\2\1 表示替换后的字符串,按照之前的分组顺序进行替换

awk

awk是一个强大的文本编辑器,逐行读取文件内容,然后输出结果。它可以读取输入流中的行,并根据指定的规则将它们分成不同的字段。然后可以对这些字段进行操作,如打印或计算。awk本身也是一个开发工具,内置代码,和java很像。

语法

awk  [选项]  '条件{动作}'  文件名

其中,[选项] 可以省略,'条件 {动作}' 是 awk 的脚本部分,文件名 是需要处理的文件名。

常用选项:

-F:指定字段分隔符。

-v:定义变量。

-f:从指定文件中读取 awk 脚本。

常用的内置函数:

length(str):返回字符串str的长度。

substr(str,start,length):返回字符串 str 从第 start 个字符开始,长度为 length 的子字符串。

split(str,arr,sep):将字符串 str 按照分隔符 sep 分割成数组 arr。

match(str,reg):在字符串 str 中查找正则表达式 reg,返回匹配的位置和长度。

常用变量:

$0:表示当前行。

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

NF:表示当前行的字段数。

NR:表示当前行号。

OFS:输出字段分隔符,默认值与输入字段分隔符一致。

案例

1、打印文件 test01.txt 内容

awk '{print}' test01.txt

awk '0{print}' test01.txt 中的0表示始终为假,即不匹配任何行。由于条件不成立,因此不会执行动作部分,即不会打印任何内容。

awk '1{print}' test01.txt 中的1表示始终为真,即匹配所有行。

2、打印文件 test01.txt 中的所有行,并在每行前面添加行号。

awk '{print NR,$0}' test01.txt

print NR,$0 表示打印当前行的行号和内容。

3、打印文件 test01.txt 中的第三行。

awk 'NR==3{print}' test01.txt

条件为 NR==3,即当前行号等于 3。

打印文件 test01.txt 中的第三行和第五行:awk 'NR==3;NR==5{print}' test01.txt

打印文件 test01.txt 中的第三行到第五行之间的内容:awk '(NR>=3)&&(NR<=5){print}' test01.txt

打印文件 test01.txt 中的偶数行:awk 'NR%2==0{print}' test01.txt

4、计算并打印出数值表达式 2的3次方 的结果。

awk 'BEGIN{print 2**3}'        或        awk 'BEGIN{print 2^3}'

5、从系统用户信息文件 /etc/passwd 中查找以 root 开头的行并打印出来。

awk '/^root/{print}' /etc/passwd

/^root/ 是一个正则表达式,表示匹配以 root 开头的行。

6、从系统用户信息文件 /etc/passwd 中查找包含 rootoperator 之间的所有行,并将它们打印出来。

awk '/root/,/operator/{print}' /etc/passwd

7、用 BEGIN 统计 test01.txt 文件中的行数并打印出来。

awk 'BEGIN{x=0};{x++};END{print x}' test01.txt

BEGIN{x=0}: 在处理输入之前执行的代码块。这里将变量 x 的初始值设置为 0。

{x++}: 对每一行执行的代码块。这里将变量 x 的值加一,相当于统计行数。

END{print x}: 在处理完整个输入之后执行的代码块。这里打印变量 x 的值,即行数。

8、从 /etc/passwd 文件的前五行中提取出每行的第五个字段,并将提取的结果打印出来。

head -n 5 /etc/passwd | awk 'BEGIN{FS=":"};{print $5}'

'BEGIN{FS=":"}': awk脚本的开始部分,在处理输入之前执行的代码块。这里设置字段分隔符为冒号 :,以便后续按字段提取数据。

9、从 /etc/passwd 文件中查找 shell 为 bash 的用户,并打印出这些用户的用户名和家目录路径。

awk -F: '$7~"bash" {print $1,$NF}' /etc/passwd

-F:选项,指示 awk 使用冒号 ‘ : ' 作为字段分隔符

$7~"bash":条件语句,用于判断当前行的第七个字段(即 shell 字段)是否包含字符串 "bash"。其中,~ 表示模式匹配,$7 表示当前行的第七个字段,"bash" 是要匹配的模式。

{print $1,$NF}:执行语句,如果条件语句成立,则执行该语句。这里打印当前行的第一个字段(即用户名)和最后一个字段(即家目录路径)。

同样的,不是 "nologin" 的用户:awk -F: '$7!~"nologin" {print $5}' /etc/passwd

10、查找家目录为 "/home/dn",且 shell 为 "/bin/bash" 的用户。

awk -F: '($6=="/home/dn") && ($7=="/bin/bash") {print $1,$NF}' /etc/passwd

11、筛选出 UID 大于 500 的用户。

awk -F: '{if ($3>500) {print $NF}}' /etc/passwd

 12、从 /etc/passwd 文件中找出 UID 和 GID 中较大的值,然后将该最大值和整行内容打印出来。

效果如下:

awk -F: '{max=($3>$4)?$3:$4;{print max,$0}}' /etc/passwd

'{max=($3>$4)?$3:$4;{print max,$0}}':是一个awk的三元表达式。($3>$4)?$3:$4 是一个条件表达式。($3>$4) 为条件,条件为真则 $3 ,为假则 $4 ,即比较第三个字段(UID)和第四个字段(GID),如果 UID 大于 GID,则将 UID 赋值给变量 max,否则将 GID 赋值给 max。然后使用 print max,$0 打印 max 和整行内容。

13、写脚本,计算并打印变量a加变量b的值。

14、以“用户名==UID”的形式输出

awk -v FS=':' -v OFS='==' '{print $1,$3}' /etc/passwd

-v FS=':':选项,指示 awk 使用冒号作为字段分隔符,并将其存储在变量 FS 中。

-v OFS='==':选项,指示 awk 使用双等号作为输出字段分隔符,并将其存储在变量 OFS 中。

15、awk数组

awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[0]}'

 'BEGIN{a[0]=10;a[1]=20;a[2]=30;print a[0]}':在开始处理之前(即 BEGIN 部分),执行的 awk 脚本代码。在这段代码中,我们创建了一个名为 a 的数组,并分别给数组的索引 012 赋值为 102030。然后使用 print 命令打印数组 a 的第一个元素,即 a[0]

16、遍历数组

awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a)print i,a[i]}'

 17、test.txt文件中有数个aaa、bbb和ccc字段。用awk分别统计它们的个数。

awk '{a[$1]++};END{for(i in a){print i,a[i]}}' test.txt

'{a[$1]++}':在每一行应用的 awk 脚本代码。$1 表示当前处理的行的第一个字段,即将其作为键存储到数组 a 中。a[$1]++ 表示对数组 a 中以 $1 为键的元素的值进行自增操作,相当于统计了 $1 出现的次数。

END{for(i in a){print i,a[i]}}:在文件处理完成之后(即 END 部分),执行的 awk 脚本代码。这段代码使用 for 循环遍历数组 a,并使用 print 命令打印每个键值对。其中,i 表示数组 a 的键,a[i] 表示键 i 对应的值,即出现的次数。

能达到类似效果的还有:cat test.txt | sort | uniq -c

 18、显示排除了 tmpfs 文件系统的磁盘的可用容量。

df | grep -v 'tmpfs' | awk '{sum+=$4} END{print "磁盘的可用容量:" sum/1024/1024"G"}'

grep -v 'tmpfs':过滤掉包含字符串 tmpfs 的行。

{sum+=$4}:在每一行中,将第四个字段(即可用容量)加入变量 sum 中。

END{print "磁盘的可用容量:" sum/1024/1024"G"}:在处理完所有行之后,使用 print 命令打印磁盘的可用容量。其中,sum/1024/1024 表示将 sum 的值从字节转换为以 GB 为单位的容量值,G 表示 GB 单位的后缀。

19、计算 /etc/ 目录下所有普通文件的总大小。

ls -l /etc/ | awk '/^-/ {sum+=$5} END{print "文件总大小:"sum/1023"M"}'

/-/:使用正则表达式匹配第一列以 - 开头(即普通文件)的行。

{sum+=$5}:在每个匹配的行中,将第五列(即文件大小)加入变量 sum 中。

END{print "文件总大小:"sum/1023"M"}:在处理完所有行之后,使用 print 命令打印文件的总大小。其中,sum/1023 表示将 sum 的值从字节转换为以 MB 为单位的大小值,M 表示 MB 单位的后缀。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值