grep正则表达式规范 在sed、awk及C语言中用正则表达式

1 正则表达式介绍

一个命令查找一个模式得到一类字符串时,这个模式应该包含以下信息:

  • 字符类:它们在模式中表示一个字符,取值范围是一类字符中的任意一个
  • 数量限定符:如IP地址的每一部分可以有1 –3个数字。
  • 各种字符类以及普通字符间的位置关系:如IP地址分四部分,用普通字符’.’隔开,每部分都可以用字符类和数量限定符描述

规定一些特殊语法表示字符类、数量限定符和位置关系,然后用这些特殊语法和普通字符一起表示一个模式,这就是正则表达式(Regular Expression)。


2 grep正则表达式的Extended规范

各种工具和编程语言所使用的正则表达式规范的语法并不相同,表达能力也各不相同,有的正则表达式规范引入很多扩展,能表达更复杂的模式,但各种正则表达式规范的基本概念都是相通的。grep所使用的正则表达式,它大致上符合POSIX正则表达式规范,此笔记学习、练习grep使用的正则表达式。


(1) 字符类

字符

含义

举例

.

匹配任意一个字符

abc.可以匹配abcd、abc9等

[]

匹配括号中的任意一个字符

[abc]d可以匹配ad、bd或cd

-

在[]括号内表示字符范围

[0-9a-fA-F]可以匹配一位十六进制数字

^

位于[]括号内的开头,匹配括号中的字符之外的任意一个字符

[^xy]匹配除xy之外的任一字符,因此[^xy]1可以匹配

a1、b1但不匹配x1、y1

[[:xxx:]]

grep工具预定义的一些命名字符类

[[:alpha:]]匹配一个字母,

[[:digit:]]匹配一个数字


(2) 数量限定符

字符

含义

举例

紧跟在它前面的单元应匹配零次或一次

[0-9]?\.[0-9]匹配0.0、2.3、.5等,由于.在正则表达式中是一个特殊字符,所以需要用\转义一下,取字面值

+

紧跟在它前面的单元应匹配一次或多次

[a-zA-Z0-9_.-]+@[a-zA-Z0-9_.-]+\.[a-zA-Z0-9_.-]+匹配email地址

*

紧跟在它前面的单元应匹配零次或多次

[0-9][0-9]*匹配至少一位数字,等价于[0-9]+,[a-zA-Z_]+[a-zA-Z_0-9]*匹配C语言的标识符

{N}

紧跟在它前面的单元应精确匹配N次

[1-9][0-9]{2}匹配从100到999的整数

{N,}

紧跟在它前面的单元应匹配至少N次

[1-9][0-9]{2,}匹配三位以上(含三位)的整数

{,M}

紧跟在它前面的单元应匹配最多M次

[0-9]{,1}相当于[0-9]?

{N,M}

应匹配至少N次,最多M次

[0-9]{1,3}\.[0-9]{1,3}匹配IP地址


(3) 位置限定符

字符

含义

举例

^

匹配行首的位置

^Content匹配位于一行开头的Content

$

匹配行末的位置

;$匹配位于一行结尾的;号,^$匹配空行

\<

匹配单词开头的位置

\<th匹配... this,但不匹配ethernet、tenth

\>

匹配单词结尾的位置

p\>匹配leap ...,但不匹配parent、sleepy

\b

匹配单词开头或结尾的位置

\bat\b匹配... at ...,但不匹配cat、atexit、batch

\B

匹配非单词开头结尾的位置

\Bat\B匹配battery,但不匹配... attend、hat...


(4) 其它特殊字符

字符

含义

举例

\

转义字符,普通字符转义为特殊字符,特殊字符转义为普通字符

普通字符<写成\<表示单词开头的位置,特殊字符.写成\.以及\写成\\就当作普通字符来匹配

()

将正则表达式的一部分括起来组成一个单元,可以对整个单元使用数量限定符

([0-9]{1,3}\.){3}[0-9]{1,3}匹配IP地址

|

连接两个子表达式,表示或的关系

n(o|either)匹配no或neither

Basic规范也有这些语法,只是字符?+{}|()应解释为普通字符,要表示上述特殊含义则需要加\转义。如果用grep而不是egrep,并且不加-E参数,则应该遵照Basic规范来写正则表达式。


3 sed与正则表达式

(1) sed简介

sed意为流编辑器(Stream Editor),在Shell脚本和Makefile中作为过滤器使用非常普遍,也就是把前一个程序的输出引入sed的输入,经过一系列编辑命令转换为另一种格式输出


sed命令不会修改文件,只是经过sed命令后输出需要部分。


(2) sed涉及的正则表达式及编辑命令

sed处理的文件既可以由标准输入重定向得到,也可以当命令行参数传入,命令行参数可以一次传入多个文件,sed会依次处理。sed的编辑命令可以直接当命令行参数传入,也可以写成一个脚本文件然后用-f参数指定,编辑命令的格式为:

/pattern/action

其中pattern是正则表达式,action是编辑命令。sed一行一行读出待处理文件,如果某一行与pattern匹配,则执行相应的action,如果一条命令没有pattern而只有action,这个action将作用于待处理文件的每一行。


sed常用编辑操作:

/pattern/p

打印匹配pattern的行

/pattern/d

删除匹配pattern的行

/pattern/s/pattern1/pattern2/

查找符合pattern的行,将该行第一个匹配pattern1的字符串替换为pattern2

/pattern/s/pattern1/pattern2/g

查找符合pattern的行,将该行所有匹配

pattern1的字符串替换为pattern2


(3) sed命令行格式

根据(2)中对sed处理的文件编辑命令的描述可得sed命令行的基本格式为:

sed option 'script' file1 file2 ...

sed option –f scriptfile file1 file2 …

  • option表示sed的可选参数,如要想只输出处理结果则option为-n。
  • ‘script’表示脚本命令[ (2)中提到的编辑命令 ]。
  • filen表示要用sed处理的文件
  • -f属option范畴,它允许将脚本命令编写成脚本文件再传给sed。

4 awk

(1) awk介绍

sed以行为单位处理文件,awk比sed强的地方在于不仅能以行为单位还能以列为单位处理文件。awk缺省的行分隔符是换行,缺省的列分隔符是连续的空格和Tab,但是行分隔符和列分隔符都可以自定义,比如/etc/passwd文件的每一行有若干个字段,字段之间以:分隔,就可以重新定义awk的列分隔符为:并以列为单位处理这个文件


(2) awk命令行格式

awk基本用法和sed类似,awk命令行的基本形式为:

awk option 'script' file1 file2 ..

awk option -f scriptfile file1 file2 ...

和sed一样,awk处理的文件既可以由标准输入重定向得到,也可以当命令行参数传入,编辑命令可以直接当命令行参数传入,也可以用-f参数指定一个脚本文件,编辑命令的格式为:

/pattern/{actions}

condition{actions}

pattern是正则表达式,actions是一系列操作(编辑命令),awk程序一行一行读出待处理文件,如果某一行与pattern匹配,或者满足condition条件,则执行相应的actions,如果一条awk命令只有actions部分,则actions作用于待处理文件的每一行。


awk命令的condition部分还可以是两个特殊的condition-BEGIN和END,对于每个待处理文件,BEGIN后面的actions在处理整个文件之前执行一次,END后面的actions在整个文件处理完之后执行一次。


(3) awk内建变量

awk命令可以像C语言一样使用变量(但不需要定义变量)。就像Shell的环境变量一样,有些awk变量是预定义的有特殊含义的:

FILENAME

当前输入文件文件名,该变量是只读的

NR

当前行的行号,该变量是只读的,R代表record

NF

当前行所拥有的列数,该变量是只读的,F代表field

OFS

输出格式的列分隔符,缺省是空格

FS

输入文件的列分融符,缺省是连续的空格和Tab

ORS

输出格式的行分隔符,缺省是换行符

RS

输入文件的行分隔符,缺省是换行符

awk还可以像C语言一样使用if/else、while、for控制结构。以前未“系统”掌握awk命令格式时做的笔记(例子):shell awk读取文件中的指定行的指定字段


5 在C语言中使用的正则表达式

POSIX规定了正则表达式的C语言库函数:regex(3)。man regex


用正则表达式匹配字符串是否为IP地址的C代码

/*Filename:	regex_in_c.c
 *Brife:	use c function to use regex
 *Author:	One fish
 *Date:		2014.8.12 Tuesday
 */
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>


int main(void)
{
	regex_t		reg;
	char		regex[] = "[0-9]{1,3}\\.[0-9]{1,3}";
	char		str[] = "172.168.13.1";
	size_t		nmatch = 1;
	regmatch_t	pmatch[1];
	char		errbuf[100];
	int		i,re;

	//Compile regex to reg	
	re	= regcomp(&reg,regex,REG_EXTENDED | REG_NEWLINE);
	if ( 0 != re ) {
		regerror(re,&reg,errbuf,100);
		printf("%s\n",errbuf);
		exit(1);
	}

	//Use reg which compiled from pattern to match substring in whole string str
	re	= regexec(&reg,str,nmatch,pmatch,0);
	if (REG_NOMATCH == re) {
		printf("No match\n");
		exit(1);
	} else if (0 == re) {
		printf("matched:\n");
		for (i = pmatch[0].rm_so; i < pmatch[0].rm_eo; ++i) {
			putchar(str[i]);
		}
		printf("\n");
		printf("%d,%d\n",pmatch[0].rm_so,pmatch[0].rm_eo);
	}

	//Free &reg used in recomp
	regfree(&reg);
	return 0;
}

编译并执行程序:

gcc -o regex_in_c regex_in_c.c

./regex_in_c

matched:

172.168.13.1

0,12

当在regcomp函数中的cflags参数中指定REG_NOSUB时nmatch和pmatch参数将会被忽略,不能再将它们的值输出来。


[2014.8.11-21.02 ---- 2014.8.12-16.29]

LCNote Over.

相关文章

正则替换html代码中img标签的src值在开发富文本信息在移动端...
正则表达式
AWK是一种处理文本文件的语言,是一个强大的文件分析工具。它...
正则表达式是特殊的字符序列,利用事先定义好的特定字符以及...
Python界一名小学生,热心分享编程学习。
收集整理每周优质开发者内容,包括、、等方面。每周五定期发...