韦德国际1946国际网址:正则表明式,Unix工具与正

作者: 韦德国际1946国际网址  发布:2019-05-28

目录

一 POSIX正则表明式

1.1 头文件

壹.二 注意事项

一.三 基本措施

1.四 POSIX正则表明式基本标准

1.伍 源码示例

一、POSIX字符类

字符类 说明
[:digit:] 任何数字
[:xdigit:] 任何十六进制数字
[:alpha:] 任何字母
[:lower:] 任何小写字母
[:upper:] 任何大写字母
[:alnum:] 任何字母或数字
[:cntrl:] ASCII控制字符(ASCII 0~31 和 ASCII 127)
[:punct:] 不属于[:alnum:]和[:cntrl:]的任何字符
[:blank:] 空格或制表符([t ])
[:space:] 任何空白字符,包括空格([fnrtv ])
[:print:] 任何可打印字符
[:graph:] 同[:print:],但不包括空格

 
留神:[和]是POSIX字符类自个儿的组成都部队分。

韦德国际1946国际网址:正则表明式,Unix工具与正则表明式的POSIX标准。 

对正则表明式有基本驾驭的读者,一定不会素不相识『d』、『[a-z] 』之类的表明式,前者相称二个数字字符,后者相称贰个之上的小写英文字母。可是只要您用过vi、grep、awk、sed之类Linux韦德国际1946国际网址,/Unix下的工具只怕会发觉,那个工具尽管协理正则表明式,语法却很分歧,照平日习贯的措施写的『d』、『[a-z] 』之类的正则表明式,往往不是无力回天辨认就是合营错误。而且,那个工具自个儿之间也设有出入,一样的构造,一时要求转义一时无需转义。那,毕竟是为啥呢?

一       POSIX正则表明式

时间戳是自 一九69 年 1 月 1 日(00:00:00 红霉素T)以来的秒数,也被称作 Unix 时间戳(Unix Timestamp)。

案由在于,Unix/Linux下的工具许多使用POSIX标准,相同的时候,POSIX标准又可分为二种流派(flavor)。所以,首先有至关重要领会一下POSIX标准。

1.1     头文件

#include <regex.h>

Unix时间戳(Unix timestamp),或称Unix时间(Unix time)、POSIX时间(POSIX time),是一种时光代表方法,定义为从格林威治时间1970年01月01日00时00分00秒起至以往的总秒数
Unix时间戳不止被利用在Unix系统、类Unix系统中,也在众多别的操作系统中被大规模运用。

POSIX规范

大规模的正则表明式记法,其实都源于Perl,实际上,正则表达式从Perl衍生出1个盛名的派别,叫做PCRE(Perl Compatible Regular Expression),『d』、『w』、『s』之类的记法,便是其一黑帮的表征。不过在PCRE之外,正则表明式还也有其余流派,举个例子下边要介绍的POSIX标准的正则表达式。

POSIX的齐全部都以Portable Operating System Interface for uniX,它由1各个典型构成,定义了UNIX操作系统应该扶助的功用,所以“POSIX标准的正则表达式”其实只是“关刘阳则表明式的POSIX标准”,它定义了BRE(Basic Regular Expression,基本型正则表明式)和ERE(Extended Regular Express,扩大型正则表达式)两大山头。在相当POSIX的UNIX系统上,grep和egrep之类的工具都服从POSIX规范,一些数据库系统中的正则表明式也契合POSIX标准。

一.二     注意事项

    但是在C 的字符串中,''表示转义前面包车型客车字符,'\'才代表贰个'',而在正则中,''也代表转义,所以3个'不荒谬'的正则在修改为C 正则时,全部的''都要倍加。

    POSIX**正则表明式有和好的一套规范,与常用的正则表明式不完全同样**。

如何在不相同编程语言中取得以往的Unix时间戳(Unix timestamp)?

Java time
JavaScript Math.round(new Date().getTime()/1000)
getTime()返回数值的单位是毫秒。因为new Date().getTime()得到的是millisecond,需要除以1000
Microsoft .NET / C# epoch = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000
MySQL SELECT unix_timestamp(now())
Perl time
PHP time()
PostgreSQL SELECT extract(epoch FROM now())
Python 先 import time 然后 time.time()
Ruby 获取Unix时间戳:Time.now 或 Time.new
显示Unix时间戳:Time.now.to_i
SQL Server SELECT DATEDIFF(s, '1970-01-01 00:00:00', GETUTCDATE())
Unix / Linux date %s
VBScript / ASP DateDiff("s", "01/01/1970 00:00:00", Now())
其他操作系统
(如果Perl被安装在系统中)
命令行状态:perl -e "print time"

BRE

在Linux/Unix常用工具中,grep、vi、sed都属于BRE这一面,它的语法看起来相比较奇异,元字符『(』、『)』、『{』、『}』必须转义之后技艺有特种意义,所以正则表达式『(a)b』只可以相称字符串 (a)b而不是字符串ab;正则表达式『a{1,2}』只可以相称字符串a{1,贰},正则表明式『a{1,2}』工夫相称字符串a只怕aa。

就此如此劳碌,是因为这一个工具的落地时间很早,正则表明式的好些个效能却是稳步发展览演出化出来的,此前这几个元字符可能并从未特殊的意义;为保障向后分外,就只能利用转义。而且有个别效果竟然向来就不支持,比方BRE就不辅助『 』和『?』量词,也不帮忙多选结构『(…|…)』和反向引用『1』、『2』…。

而是后天,纯粹的BRE已经不多见了,终归我们已经认为正则表达式“理所应当”扶助多选结交涉反向引用等成效,未有真正太不方便人民群众。所以固然vi属于BRE流派,但提供了这一个意义。GNU也对BRE做了扩充,帮衬『 』、『?』、『|』,只是利用时务必写成『 』、『?』、『|』,而且也帮忙『1』、『二』之类反向引用。那样,GNU的grep等工具固然名义上属于BRE流,但更方便的称号是GNU BRE。

壹.3     基本方式

怎么在差别编制程序语言中落实Unix时间戳(Unix timestamp) → 普通日子?

Java

String date = new java.text.SimpleDateFormat("dd/MM/yyyy HH:mm:ss").format(new java.util.Date(Unix timestamp * 1000))

java.util.Date的入参是millisecond。而Unix timestamp的单位是s

JavaScript

先 var unixTimestamp = new Date(Unix timestamp * 1000) 然后 commonTime = unixTimestamp.toLocaleString()

js中Date需要的入参是millisecond

Linux date -d @Unix timestamp
MySQL from_unixtime(Unix timestamp)
Perl 先 my $time = Unix timestamp 然后 my ($sec, $min, $hour, $day, $month, $year) = (localtime($time))[0,1,2,3,4,5,6]
PHP date('r', Unix timestamp)
PostgreSQL SELECT TIMESTAMP WITH TIME ZONE 'epoch' Unix timestamp) * INTERVAL '1 second';
Python 先 import time 然后 time.gmtime(Unix timestamp)
Ruby Time.at(Unix timestamp)
SQL Server DATEADD(s, Unix timestamp, '1970-01-01 00:00:00')
VBScript / ASP DateAdd("s", Unix timestamp, "01/01/1970 00:00:00")
其他操作系统
(如果Perl被安装在系统中)
命令行状态:perl -e "print scalar(localtime(Unix timestamp))"

ERE

在Linux/Unix常用工具中,egrep、awk则属于ERE这2头,。纵然BRE名叫“基本”而ERE名称为“扩大”,但ERE并无需合作BRE的语法,而是自成1体。由此在那之中的元字符不用转义(在元字符此前增多反斜线会撤废其出色含义),所以『(ab|cd)』就可以相配字符串ab恐怕cd,量词『 』、『?』、『{n,m}』能够间接行使。ERE并不曾分明规定支持反向引用,可是洋洋工具都扶助『1』、『2』之类的反向引用。

GNU出品的egrep等工具就属于ERE流(改良确的名字是GNU ERE),但因为GNU已经对BRE做了无数扩大,所谓的GNU ERE其实只是个说法而已,它有些职能GNU BRE都有了,只是元字符没有供给转义而已。

上面包车型地铁报表简要表达了二种POSIX流派的差距[1](其实,现在的BRE和ERE在功能上并不曾什么分别,首要的歧异是在元字符的转义上)。

两种POSIX流派的评释

 

流派

说明

工具

BRE

(、)、{、}都必须转义使用,不支持 、?、|

grep、sed、vi(但vi支持这些多选结构和反向引用)

GNU BRE

(、)、{、}、 、?、|都必须转义使用

GNU grep、GNU sed

ERE

元字符不必转义, 、?、(、)、{、}、|可以直接使用,1、2的支持不确定

egrep、awk

GNU ERE

元字符不必转义, 、?、(、)、{、}、|可以直接使用,支持1、2

grep –E、GNU awk

 

为了有利于查阅,上边再用一张表格列出基本的正则效能在常用工具中的表示法,个中的工具GNU的本子为准。

常用Linux/Unix工具中的表示法

 

PCRE记法

vi/vim

grep

awk

sed

*

*

*

*

*

?

=

?

?

?

{m,n}

{m,n}

{m,n}

{m,n}

{m,n}

b *

< >

< >

< >

y < >

(…|…)

(…|…)

(…|…)

(…|…)

(…|…)

(…)

(…)

(…)

(…)

(…)

1 2

1 2

1 2

不支持

1 2

 

注:PCRE中常用b来表示“单词的序曲或截至地方”,但Linux/Unix的工具中,平常用<来协作“单词的胚胎地方”,用>来协作“单词的扫尾地方”,sed中的y能够而且匹配那八个职位。

1.3.1     regcomp

哪些在不一致编程语言中完成平时日子 → Unix时间戳(Unix timestamp)?

 

Java
Date date = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss").parse("01/01/1970 01:00:00");
long epoch = date.getTime();

这个地方是不是需要除以1000转换成s呢?

JavaScript

var commonTime = new Date(Date.UTC(year, month - 1, day, hour, minute, second))

这个地方是不是需要除以1000转换成s呢?

MySQL SELECT unix_timestamp(time)
时间格式: YYYY-MM-DD HH:MM:SS 或 YYMMDD 或 YYYYMMDD
Perl 先 use Time::Local 然后 my $time = timelocal($sec, $min, $hour, $day, $month, $year);
PHP mktime(hour, minute, second, day, month, year)
PostgreSQL SELECT extract(epoch FROM date('YYYY-MM-DD HH:MM:SS'));
Python 先 import time 然后 int(time.mktime(time.strptime('YYYY-MM-DD HH:MM:SS', '%Y-%m-%d %H:%M:%S')))
Ruby Time.local(year, month, day, hour, minute, second)
SQL Server SELECT DATEDIFF(s, '1970-01-01 00:00:00', time)
Unix / Linux date %s -d"Jan 1, 1970 00:00:01"
VBScript / ASP DateDiff("s", "01/01/1970 00:00:00", time)

var oldTime = (new Date("2011/11/11 20:10:10")).getTime(); //得到毫秒数
var newTime = new Date(oldTime); //就得到普通的时间了

一向传入飞秒数作为参数,给Date对象即可赢得普通的小时了,然后经过getHours,getFullYear等措施获得年月日,时分秒了

 

创建三个日期对象:

var objDate=new Date([arguments list]); 

参数方式有以下各类:

1)new Date("month dd,yyyy hh:mm:ss");
2)new Date("month dd,yyyy");
3)new Date(yyyy,mth,dd,hh,mm,ss);

在先后中本人动用的第三种开头化方法,总是展现格式化的参数不得法,仔细看了一下决然借使整型的工夫够,作者传递的是字符串

4)new Date(yyyy,mth,dd);
5)new Date(ms);

急需注意最终1种样式,参数表示的是急需创制的时光和 奇霉素T时间一玖6玖年五月三日里面离开的飞秒数。各个函数的意义如下:

month:用英文 表示月份名称,从January到December

mth:用整数表示月份,从(1月)到11(12月)

dd:表示2个 月首的第几天,从一到31

yyyy:四个人数表示的年份

hh:小时数,从0(午夜)到23(晚11点)

mm: 分钟数,从0到59的整数

ss:秒数,从0到59的整数

ms:阿秒数,为当先等于0的整数

如:

new Date("January 12,2006 22:19:35"); 
new Date("January 12,2006"); 
new Date(2006,0,12,22,19,35); 
new Date(2006,0,12); 
new Date(1137075575000); 

上边包车型大巴种种创设方式都意味着200陆 年5月二2日这一天。 

 

POSIX字符组

在好几文书档案中,你还恐怕会发现邻近『[:digit:]』、『[:lower:]』之类的表示法,它们看起来简单精通(digit正是“数字”,lower正是“小写”),但又很想获得,那正是POSIX字符组。不止在Linux/Unix的分布工具中,以至有的成为语言中都出现了这几个字符组,为制止思疑,这里有不能缺少简介它们。

在POSIX规范中,『[a-z]』、『[aeiou]』之类的记法依旧是法定的,其意思与PCRE中的字符组也并未有分别,只是那类记法的高精度名称是POSIX方括号表明式(bracket expression),它至关心注重要用在Unix/Linux系统中。POSIX方括号表示法与PCRE字符组的最尊敬差别在于:POSIX字符组中,反斜线不是用来转义的。所以POSIX方括号表示法『[d]』只可以同盟和d四个字符,而不是『[0-9]』对应的数字字符。

为了缓和字符组中国和澳洲常含义字符的转义难题,POSIX方括号表示法规定,要是要在字符组中发挥字符](而不是作为字符组的截止标识),应当让它紧跟在字符组的开方括号之后,所以POSIX中,正则表明式『[]a]』能相配的字符正是]和a;假设要在POSIX方括号表示法中发布字符-(而不是限制表示法),必须将它紧挨在闭方括号]之前,所以『[a-]』能相配的字符正是a和-。

POSIX标准也定义了POSIX字符组,它相仿等价于于PCRE的字符组简记法,用2个有直观意义的名字来表示某一组字符,举个例子digit表示“数字字符”,阿尔法表示“字母字符”。

而是,POSIX中还会有一个值得注意的定义:locale(常常翻译为“语言情形”)。它是1组与语言和文化有关的设定,包含日期格式、货币币值、字符编码等等。POSIX字符组的意思会依靠locale的变动而改换,上面包车型大巴表格介绍了大规模的POSIX字符组在ASCII语言遇到与Unicode语言蒙受下的意义,供我们参谋。

POSIX字符组

 

POSIX字符组

说明

ASCII语言环境

Unicode语言环境

[:alnum:]*

字母字符和数字字符

[a-zA-Z0-9]

[p{L&}p{Nd}]

[:alpha:]

字母

[a-zA-Z]

p{L&}

[:ascii:]

ASCII字符

[x00-x7F]

p{InBasicLatin}

[:blank:]

空格字符和制表符

[ t]

[p{Zs}t]

[:cntrl:]

控制字符

[x00-x1Fx7F]

p{Cc}

[:digit:]

数字字符

[0-9]

p{Nd}

[:graph:]

空白字符之外的字符

[x21-x7E]

[^p{Z}p{C}]

[:lower:]

小写字母字符

[a-z]

p{Ll}

[:print:]

类似[:graph:],但包括空白字符

[x20-x7E]

P{C}

[:punct:]

标点符号

[][!"#$%&'()* ,./:;<=>?@^_`{|}~-]

[p{P}p{S}]

[:space:]

空白字符

[ trnvf]

[p{Z}trnvf]

[:upper:]

大写字母字符

[A-Z]

p{Lu}

[:word:]*

字母字符

[A-Za-z0-9_]

[p{L}p{N}p{Pc}]

[:xdigit:]

十六进制字符

[A-Fa-f0-9]

[A-Fa-f0-9]

 

注1:标记*的字符组简记法并不是POSIX标准中的,但使用过多,一般语言中都提供,文书档案中也会产出。

注二:对应的Unicode属性请参见本体系文章已经刊发过的有关Unicode的一部分。

POSIX字符组的应用有所不一致。首要不一致在于,PCRE字符组简记法能够脱离方括号直接出现,而POSIX字符组必须出现在方括号内,所以一样是优秀数字字符,单独出现时,PCRE中得以一直写『d』,而POSIX字符组就必须写成『[[:digit:]]』。

Linux/Unix下的工具中,一般都能够平昔行使POSIX字符组,而PCRE的字符组简记法『w』、『d』等则繁多不扶助,所以只要您看看『[[:space:]]』而不是『s』,一定毫无感到意外。

唯独,在常用的编制程序语言中,Java、PHP、Ruby也支撑选择POSIX字符组。在那之中Java和PHP中的POSIX字符组都以遵循ASCII语言景况开始展览相称;Ruby的意况则要复杂一点,Ruby 一.八按照ASCII语言遭受展开匹配,而且不辅助『[:word:]』和『[:alnum:]』,Ruby 一.玖安分守纪Unicode语言境遇开始展览相称,同有的时候候协理『[:word:]』和『[:alnum:]』。

说明:关李欣蔓则表达式的层层作品到此即甘休,小编近来早就变成了一本关张永琛则表明式的图书,在那之中更详实也更宏观地讲学了正则表明式使用中的各类主题素材。该书暂定名《正则导引》,揣度最近上市,风乐趣的读者敬请关切。


[1] 关于ERE和BRE的事无巨细规范,可以参见

有关小编

余晟,技师,曾任抓虾网高档顾问,现就职于盛大立异院,感兴趣的取向总结找寻和遍及式算法等。翻译爱好者,译有《通晓正则表达式》(第3版)和《技巧官员之路》,近期正值创作《正则表明式傻瓜书》(暂定名),希望为国内开拓同行进献1本实用的正则表达式教程。


感谢王莎莎峰对本文的妄想和核查。

给InfoQ普通话站投稿或然参预内容翻译专门的学业,请邮件至editors@cn.infoq.com。也迎接我们参预到InfoQ中文站用户钻探组中与大家的编写和其他读者对象交换。


函数原型

  int regcomp(regex_t *preg, const char *regex, int cflags);

功能

  编写翻译正则表明式,以便regexec方法应用。

参数含义

preg

  preg是3个针对性编写翻译后的正则表明式p意思是pointer,reg意思是regex_t类型。

  regex_t是一个结构体数据类型,用来存放在编写翻译后的正则表明式,它的分子re_nsub用来积攒正则表明式中的子正则表明式的个数,子正则表明式便是用圆括号包起来的有的表达式。

regex

  描述正则表明式的字符串。

cflags

  决定编写翻译的类型。

    REG_EXTENDED

  扩张的正则表明式,假如不安装则为主干的正则表明式。

    REG_ICASE

  不区分轻重缓急写。

   REG_NOSUB

  不用存款和储蓄相配后的结果。

  要是设置该标记位,那么在regexec将忽略nmatch和pmatch五个参数。

   REG_NEWLINE

  识别换行符。

      ‘^’相称行的伊始, 不管regexec中是或不是设置eflags为REG_NOTBOL

   ‘$’相配行的末尾, 不管regexec中是或不是设置eflags为REG_NOTEOL

   举个例子:pattern=”^a$” 被检查测试字符串为”na”,那么设置REG_NEWLINE本领同盟成功。

返回值

       成功重返0

     退步重回错误码

1.3.2     regexec

本文由韦德国际1946发布于韦德国际1946国际网址,转载请注明出处:韦德国际1946国际网址:正则表明式,Unix工具与正

关键词: 正则表达式 19468282伟德