正则表达式及相关命令的学习笔记
正则表达式的概念
正则表达式英文为“Regular Expressions”,是一种匹配字符串的模式。
主要用来匹配字符串和替换字符串。
注意:正则表达式与文件名通配符规则不同。
最基本的正则表达式
正则表达式版本繁多,最基本的正则表达式只有六个元字符(特殊字符):.
、\
、[
、^
、$
、*
,除了以上六个元字符外,其它字符与其自身匹配。
圆点
.
匹配任何一个字符,如.
可以匹配字符a
、b
、1
、2
……
反斜线
\
为转义字符,可以用来取消后面一个元字符的特殊含义,比如:\*
匹配*
本身这个字符,而不是元字符*
的特殊含义。转移字符后面紧跟的不应该是除元字符以外的字符。
之后的软件对正则表达是进行了扩展,使反斜线后面可以跟其它字符,表示其它特殊含义。
定义集合
左方括号[
用来与右方括号]
组合定义一个集合,匹配集合中的任意一个字符,如:[abc]
匹配a
或b
、c
。
圆点,星号,反斜线在方括号内没有特殊含义,仅表示其自身,如:[.*\]
匹配字符.
或*
、\
。
可以用减号-
定义一个区间,如:[a-z]
表示26个小写字母,[a-zA-Z0-9]
表示26个字母和数字。
[][]
表示含左右方括号两个字符的集合。(这里有点迷惑)
减号在最后,则失去表示区间的意义,如:[az-]
匹配字符a
或z
、-
。
用^
放在开头,表示补集。比如:[^a-z]
匹配一个不是小写字母的字符
星号
*
表示前面的单字符正则表达式出现0次或者多次,单字符正则表达式是指表示一个字符的正则表达式,如:表示一个字符a
的正则表达式有a
、.
、[a-z]
……。
*
的用法举例:
12*4
可以匹配字符串14
(2
出现0次)、12224
(2
出现3次)……[A-Z][0-9]*
可以匹配[A-Z]
、[A-Z][0-9]
、[A-Z][0-9][0-9]
等正则表达式匹配的字符串
锚点
锚点有两个:$
和^
。
$
放在正则表达式的尾部时表示匹配的字符串在行尾,否则匹配字符$
自身,如:123$
匹配行尾的字符串123
,$123
匹配字符串$123
。
^
放在正则表达式的首部时表示匹配的字符串在行首,否则匹配字符^
自身,如:^123
匹配行首的字符串123
,123^
匹配字符串123^
。
在vi编辑文件的时候,可以用以下的命令删除10-50行的每行行首的4个空格(下面空白处是4个空格):
10,50s/^ //g
正则表达式的扩展
正则表达式的扩展主要有ERE
、PCRE
(Perl语言兼容的扩展正则表达式)。
扩展的正则表达式和基本正则表达式的规则是不兼容的。
下面是一些扩展的简单介绍。
分组
用圆括号()
表示分组,如:(xy)*
可匹配字符串xy
,xyxy
,xyxyxy
……也就是把一个分组当作一个整体来看待。
在圆括号中还可以使用|
表示逻辑“或”,如:(pink|green)
可以与字符串pink
或green
匹配。
重复次数定义
可以使用+
表示重复1次或多次,?
表示重复0次或1次。
还可以限定重复次数\{m,n\}
,例如:[0-9]\{6,10\}
可以匹配6-10位数字。
命名的与预定义集合
[[:xdigit:]]
表示十六进制数字,\d
表示数字,\D
表示非数字等等
正则表达式相关命令
行筛选grep
命令grep、egrep、fgrep用于在文件中查找字符串,是逐行筛选的。
grep语法如下:
grep 模式 文件名列表
可以处理多个文件,所以后面可以提供一系列的文件名做参数。
模式使用正则表达式的模式。
egrep使用扩展正则表达式ERE描述的模式;
fgrep用于快速搜索指定字符串,是按照字符串搜索而不是按照正则表达式模式搜索。
grep的模式选项有:
- -F,–fixed-strings 按照字符串搜索而不是按照正则表达式模式搜索,同fgrep命令
- -G,–basic-regexp 使用基本正则表达式模式
- -E,–extended-regexp 使用扩展正则表达式ERE模式,同egrep命令
- -P,–perl-regexp 使用Perl语言兼容的扩展正则表达式模式(PCRE)
使用man pcresyntax
可以查阅PCRE的语法。
其它常用选项:
- -n 显示行号
- -v 显示所有不匹配的行,不加这个选项是显示匹配的行
- -i 忽略字母大小写
流编辑sed
用法:
sed '命令' 文件名列表
一个命令sed -e '命令1' -e '命令2' -e '命令3' 文件名列表
多个命令sed -f 命令文件 文件名列表
命令太多可卸载文件里,命令文件的每行为一个命令
常用的命令是替换命令,比如: s/regx/string/g
,开头的s
表示把正则表达式regx匹配的字符串替换成字符串string,g
表示这一行全部匹配的字符串都进行替换。
正则表达式中添加\(
和\)
不影响匹配操作,并且可以使用\0
表示匹配的整个字符串,\1
,\2
,\3
等表示第1、2、3等个\(
和\)
之间匹配到的字符串,例如:
s/\([a-zA-Z_][a-zA-Z0-9_]*\)->number/\1->num/g
使用上面的命令可以把所有形如str->number
的字符串替换成str-num
,这里的\1
就是匹配到的str
。
注意:和大多数文本处理命令一样,输入从标准输入或者文件获取;而输出即编辑结果则输出到标准输出,而不是修改原文件。
文本加工awk
awk用来逐行扫描进行文本处理,相当于一门小型语言。
用法:
awk '程序' 文件名列表
awk -f 程序文件名 文件名列表
当程序较多,可以写在一个文件内,文件的每行为一个程序
程序的格式为:条件 {动作}
,awk自动对每行文本执行条件判断,满足条件执行动作。
输入的文件的每行作为一个“记录”,变量NR就是行号;每行用空格分隔开的部分,叫做记录的“域”,内置变量$1
是第1域内容,$2
是第2域内容,依次类推。$0
是整行内容。
条件
条件可以是使用与C语言类似的关系运算符、逻辑运算符等;也可以使用正则表达式的模式匹配/regexpr/
,包含该模式的行,执行动作。
特殊的条件:
- 不指定任何条件,对所有文本行执行动作
- BEGIN,开始处理所有文本行之前执行动作
动作
描述“动作”时,简单的用法有:
- 定义变量
- 加减乘除等算术逻辑运算
- 正则表达式匹配运输符(用作条件判断)
~
、!~
例如:$2 ~ "[1-9][0-9]*"
- 流程控制(与C语言类似)
条件判断if
循环控制for - 打印输出:
print 变量1,变量2, ...
printf("格式字符串", 变量1, 变量2, ...)
和C语言一样
举例
现有下列输出的文本信息:
$ cat wr.c
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
int main(char argc, char *argv[])
{
int fd;
fd = open(argv[1], O_WRONLY);
if (fd == -1) {
printf("ERROR %d: %m\n", errno);
printf("ERROR [%s]\n", strerror(errno));
}
}
可以使用awk实现添加行号,类似命令cat -n wr.c
:
$ awk '{printf("%d: %s\n", NR, $0);}' wr.c
1: #include <fcntl.h>
2: #include <stdio.h>
3: #include <errno.h>
4: #include <string.h>
5:
6: int main(char argc, char *argv[])
7: {
8: int fd;
9:
10: fd = open(argv[1], O_WRONLY);
11: if (fd == -1) {
12: printf("ERROR %d: %m\n", errno);
13: printf("ERROR [%s]\n", strerror(errno));
14: }
15: }
列出大小大于2000字节的文件:
$ ls -al | awk '$5 > 2000 {print $0}'