Skip to content

Linux笔记05:正则表达式与文本处理

正则表达式的概念

正则表达式 RegularExpressions 应用范围:字符串匹配操作和替换操作

  • 举例:Linux中的 vimore grep yacc lex awk sed
  • 其他:Visual Studio,Word等文本编辑器

正则表达式的功能:描述一个字符串模式

注意:

  • 正则表达式规则与文件名通配符规则不同
    • 正则表达式规则用于文本处理的场合
    • 文件名匹配规则用于文件处理的场合
  • 不同软件对正则表达式的定义会有差异

元字符和集合

元字符:正则表达式的特殊字符

  • 6个元字符:. * [ \ ^ $
  • 其它字符与其自身匹配

转义:用反斜线可以取消特殊字符的特殊含义。如:正则表达式 end\. 只与字符串 end. 匹配。

单字符正则表达式

长的正则表达式由单字符正则表达式构成

  • 非特殊字符与其自身匹配
  • 转义字符(\): \. \* \$ \^ \[ \\
  • 转义字符后除以上六种之外的不该出现其他字符,例如:不该出现\u,这样的组合被视为undefined(未定义的),后出的软件有可能会有特殊的解释
  • 圆点(.):匹配任意单字符

定义集合

基本用法:在一对方括号之间的字符为集合的内容,圆点(.),星号(*),反斜线(\)在方括号内时,代表它们自己。

如:单字符正则表达式 [abcd] 与a或b,c,d匹配,[\*.] 可匹配3个单字符

  • 用减号 - 定义一个区间
    • [a-d] [A-Z] [a-zA-Z0-9]
    • [][] 集合含左右中括号两个字符
    • 减号在最后,则失去表示区间的意义,如 [ad-] 只与3个字符匹配
  • ^ 表示补集
    • ^ 在开头,则表示与集合内字符之外的任意字符匹配,如:[^a-z] 匹配任一非小写字母、[^][] 匹配任一非中括号字符
    • ^ 不在开头,则失去其表示补集的意义,如:[a-z^] 能匹配27个单字符

组合与锚点

单字符正则表达式的组合

串结:多个单字符正则表达式连接在一起。

星号(*:单字符正则表达式后跟 *,匹配此单字符正则表达式的0次或任意多次出现

例如

  • 正则表达式 12*4 与字符串 1234 不匹配,与 1224,12224,14 匹配
  • 正则表达式 [A-Z][0-9]* 与 A,A1,C45,D768 匹配,与 b64512,T56t 不匹配
  • 正则表达式 [Cc]hapter *[1-4]* 号前有一个空格,允许数字 1-4 之前有多个或者0个空格。可匹配Chapter2, chapter 3等等。
  • 正则表达式 a\[i] *= *b\[j] *\* *c\[k] 匹配字符串 a[i]=b[j]*c[k],容许等号和星号两侧有空格
  • 在vi中使用 :1,$s/[0-9]*/xx/g

锚点:$^

$ 在尾部时有特殊意义,否则与其自身匹配

例如:

  • 123$ 匹配文件中行尾的 123,不在行尾的 123 字符不匹配
  • $123 与字符串 $123 匹配
  • .$ 匹配行尾的任意字符

^ 在首部时有特殊意义,否则与其自身匹配

例如:

  • ^printf 匹配行首的 printf 字符串,不在行首的 printf 串不匹配
  • Hel^lo 与字符串 Hel^lo 匹配
  • 在vi中使用 :10,50s/^ //g 删除10-50行的每行行首的4个空格

正则表达式扩展

  • ERE:扩展的正则表达式
  • PCRE: Perl-compatible regular expression

对**基本正则表达式(BRE)**进行了改进:

  • 表示分组:圆括号()
  • 表示逻辑运算:表示逻辑 “或” 的符号|
    • (xy)* 可匹配空字符串,xy,xyxy,xyxyxy
    • (pink|green) 与pink或green匹配
  • 重复次数定义:与星号地位类似的 +?,限定重复次数 \{m,n\}
    • * 号表示它左边的单字符正则表达式的0次或多次重复
    • + 号表示1次或多次:[0-9]+ 匹配长度至少为1数字串
    • ? 表示0次或一次: a?匹配零个或一个a
    • 限定重复次数 \{m,n\},例如:[1-9][0-9]\{6,8\}匹配7-9位数字,首位非0
  • 命名的预定义集合 [[:xdigit:]] 十六进制数字;\d 数字 \D非数字
  • ^$ 更灵活的锚点定义

行筛选 grep

  • grep/egrep/fgrep:在文件中查找字符串(筛选)
  • sed:流编辑(加工)
  • awk:逐行扫描进行文本处理的一门语言(筛选与加工)

grep 在文件中查找字符串

grep: Global regular expression print

语法: grep 模式 文件名列表

举例:

  • grep O_RDWR *.h
  • ps -ef | grep liang
  • ls -l / | grep '^d' | wc –l
  • grep '[0-9]*' shudu.c
  • grep'[0-9][0-9]*' shudu.c

egrep 使用扩展正则表达式ERE描述模式,在指定模式方面比grep更灵活。

fgrep快速搜索指定字符串,按字符串搜索而不是按模式搜索。

grep选项:

  • -F, --fixed-strings Fixed strings (instead of regular expressions)
  • -G, --basic-regexp Basic regular expression (BRE)
  • -E, --extended-regexp Extended regular expression (ERE)
  • -P, --perl-regexp Perl-compatible regular expression (PCRE)
  • 查PCRE语法:man pcresyntax
  • -n 显示时每行前面显示行号
  • -v 显示所有不包含模式的行
  • -i 字母比较时忽略字母的大小写

例:

  • grep -n main *.c :查找含有正则表达式main的行,并打印行号;当文件数超过一个时,除了输出行号,还输出文件名。
  • grep -v '[Dd]isable' dev.stat>dev.active :不输出文件中所有含有指定模式的行,生成新文件。
  • grep-i richard telnos :在文件中检索字符串 richard ,不区分字母的大小写。

流编辑 sed 和正则表达式替换

sed:流编辑

用法:

  • sed ‘命令’ 文件名列表
  • sed –e ‘命令1’ –e ‘命令2’ –e ‘命令3’ 文件名列表
  • sed -f 命令文件 文件名列表

举例:

1
tail -f pppd.log | sed 's/145\.37\.23\.26/桥西/g'
1
tail -f pppd.log | sed -f sed.cmd

其中sed.cmd文件:

1
2
3
s/145\.37\.23\.26/桥西/g
s/102\.157\.23\.109/柳荫街/g
s/145\.37\.123\.57/大山子/g
1
cat pm.txt | sed 's/\[[^][]*]//g'

模式描述中增加 \(\) :在正则表达式中圆括号,仍然代表它自身,在正则表达式中出现的 \(\) 不影响匹配操作。

1
2
[a-zA-Z_][a-zA-Z0-9_]*->number
\([a-zA-Z_][a-zA-Z0-9_]*\)->number

替换字符串中的 \0 \1 \2 ……

举例:

  • s/\([a-zA-Z_][a-zA-Z0-9_]*\)->number/\1->num/g
  • 将日期格式“月-日-年”改为“年.月.日”, 比如:将04-26-1997替换为1997.04.26使用命令:s/\([0-9][0-9]\)-\([0-9][0-9]\)-\([0-9][0-9]*\)/\3.\1.\2/g
  • 生成文件改名的命令[快视频www.kuai-vdo.com]-电视剧《三国演义》中文字幕_1080p高清_央视1994版-69.rmvbsed 's/.*-\([0-9][0-9]\).rmvb/mv \0第\1集.rmvb/'

复杂筛选及加工 awk

awk:逐行扫描进行文本处理的一门语言

a.w.k 分别为该程序的三位设计者姓氏的第一个字母

用法:

  • awk ‘程序’ 文件名列表
  • awk -f 程序文件名 文件名列表
  • 程序 条件{动作}
  • awk 自动对每行文本执行条件判断,满足条件执行动作(内置循环)
  • 允许多段程序:多段程序间用空格或分号隔开

处理方式:

  • 输入文件的每行作为一个“记录”,变量NR就是行号
  • 每行用空格分隔开的部分,叫做记录的“域”
    • 内置变量 $1 是第1域内容,依次,$2 是第2域内容,……
    • 特别的,$0 指的是整个这一行的内容
  • awk 的处理为:符合条件的行,执行相应的动作

awk 描述条件的方法:

  • 使用与C语言类似的关系算符
  • 使用与C语言类似的逻辑算符
  • 正则表达式的模式匹配 /regexpr/:包含该模式的行,执行动作
  • 特殊的条件
    • 不指定任何条件,对所有文本行执行动作
    • BEGIN 开始处理所有文本行之前执行动作
    • END 处理完所有文本行之后执行动作

awk 描述动作的方法:

  • 自定义变量
  • 加减乘除等算术逻辑运算
  • 正则表达式匹配运算符(用作条件判断)~ !~ 例如:$2 ~ "[1-9][0-9]*"
  • 流程控制(与C语言类似): if for
  • print 变量1, 变量2,……
  • printf(”格式串”,变量1,变量2,……)

awk 举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ ps -ef | grep guest
guest 669 668 0 11:27:13 ttyp1 00:00:00 -sh
guest 678 669 0 11:27:18 ttyp1 00:00:00 vi
$ ps -ef | awk'/guest/{ printf("%s ",$2); }'
669 678
$ awk '{printf("%d: %s\n",NR,$0); }' test.c
1: main()
2: {
3: printf("Hello!\n");
4: }
$ date
Thu May 27 22:02:22 BEIDT 2004
$ date | awk '{print $4}'
22:02:42
$ ls -s | awk '$1 > 2000 { print $2 }'
disk.img5document.pdf
linux-src.tar.Z
pppd.log

About this Post

This post is written by Holger, licensed under CC BY-NC 4.0.

#Linux #正则表达式