非字符串正则表达式,使regexp更抽象

nsre的Python项目详细描述


正则表达式用于匹配字符串,但是 这个概念可以应用到任何其他领域。这个引擎能让你匹配 使用相同类型构造的任何类型对象的任何列表 正则表达式允许。

这个算法是基于Russ Cox的this article,又名 使用汤姆森NFA算法(因为它显然更有效 但主要是因为这是我对重引擎的第一个解释 理解)。

然而,这个软件包还不支持?正则表达式语法 每个人都习惯了(因为它允许做不同的事情)。

Note — The current implementation is a pile of crap because I have no idea what I’m doing

安装

pip install nsre

然后从您的项目中,您可以

fromnsreimport*

概念演示

例如,假设您有一个字典列表,其中有一个type 指示内容类型的键。你想确认一下 列表中的模式。假设您想要一个序列,如果image,那么 有一个附加的caption,然后所有这些后面跟着一系列 text

从概念上讲,它希望这样

(image caption?)* text+

它一旦转换为nsre,看起来就像这样

fromnsreimport*re=AnyNumber(Symbol(KeyHasValue("type","image"))+Maybe(KeyHasValue("type","caption")))+Range(KeyHasValue("type","text"),min=1)assertre.match([{"type":"image","url":"https://img1.jpg"},{"type":"image","url":"https://img2.jpg"},{"type":"image","url":"https://img3.jpg"},{"type":"caption","text":"Image 3"},{"type":"image","url":"https://img4.jpg"},{"type":"caption","text":"Image 4"},{"type":"image","url":"https://img5.jpg"},{"type":"text","text":"Hello"},{"type":"text","text":"Foo"},{"type":"text","text":"Bar"},])

示例

因为所有这些都很抽象,让我们来看看 示例:

字符串re

假设你想match a string, 传统的re是:

"([^"\\]|\\.)*"

您可以将其转换为:

re=(Symbol('"')+AnyNumber(Symbol(Neg(InSet('"\\')))|Chain(["\\",All()]))+Symbol('"'))

电子邮件验证

关于如何验证电子邮件地址有一个值得注意的争论, 但是,让我们考虑以下表达式作为练习:

[a-z]+([\.-][a-z]+)*@[a-z]+([\.\-][a-z]+)*\.[a-z]+

现在让我们看看在nsre中是如何转换的:

letter=ChrRanges(("a","z"))join=ChrRanges((".","."),("-","-"))re=(Range(letter,min=1)+AnyNumber(Symbol(join)+Range(letter,min=1))+Symbol("@")+Range(letter,min=1)+AnyNumber(Symbol(join)+Range(letter,min=1))+Symbol(".")+Range(letter,min=1))assertre.match("remy.sanchez@with-madrid.com")

参考

提供两种对象:

  • 比较器-基本上相当于编写a[abc]在正则表达式中。它将做一个测试(等于 实例等)在所考虑的值上,以查看它是否匹配。
  • fsm-构建用于测试 正则表达式。这些对象与诸如*?

比较器

InSet

检查是否在集合中找到比较的值(比查找 它在列表中,但这意味着基类型t必须是散列的)。

assertSymbol(InSet([1,2,3])).match([1])

InList

检查是否在列表中找到比较的值。意思是 基类型t必须与__eq__()相当。

assertSymbol(InList([1,2,3])).match([1])

IsInstance

测试提供的值是否是通过的任何类的实例 给构造函数。

assertSymbol(IsInstance(A,B,C)).match([A()])

AttributeHasValue

测试比较后的值,看看它们的attribute是否具有 value

classFoo:foo='bar'assertSymbol(AttributeHasValue('foo','bar')).match([Foo()])

KeyHasValue

测试比较后的dict,看看它们的key是否具有正确的value

assertSymbol(KeyHasValue('foo','bar')).match([{'foo':'bar'}])

Neg

否定任何比较器或原始值的输出

assertSymbol(Neg('a')).match('b')assertnotSymbol(Neg('a')).match('a')

All

匹配任何东西。

assertSymbol(All()).match('a')assertSymbol(All()).match([1])

ChrRanges

对于给定的字符,检查它是否在给定的范围内。

assertSymbol(ChrRanges(('a','z'),('A','Z'))).match('X')

fsm

符号

精确匹配1个符号

re=Symbol("a")assertre.match("a")assertnotre.match("b")assertnotre.match("aa")

链条

完全匹配一系列符号

re=Chain('hello')assertre.match('hello')

+

将两个规则相邻放置

re=Symbol('h')+Symbol('e')+Symbol('l')+Symbol('l')+Symbol('o')assertre.match('hello')

|

分支不同的选项

re=Chain('My name is ')+(Chain('Foo')|Chain('Bar'))assertre.match('My name is Foo')

可能(相当于?

匹配0个或1个匹配项

re=Chain('Call me')+Maybe(Chain(' maybe'))assertre.match('Call me')assertre.match('Call me maybe')

任意数(相当于*

匹配0个或多个匹配项

re=AnyNumber(Chain("na "))+Chain("Batman!")assertre.match("na na na na Batman!")

范围(相当于{min,max}+

来自m的匹配最大出现次数。默认情况下min为0 而max是无限的。

re=Maybe(Chain('Cam'))+Range('a',min=3)+Chain('rgh')assertre.match('Camaaaaaaaargh')

性能

太可怕了

开发

nsre本身没有依赖项,但是有几个 在requirements.txt中帮助开发的包。

安装开发依赖项

pip install -r requirements.txt

更新依赖项

编辑requirements.txt,然后运行

make venv

运行测试

单元测试使用pytest运行。

make test

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java是否可以将一半的文本绘制成不同的颜色?   java如何在Eclipse中生成Javadoc HTML文件?   带有时间戳的java“select”preparedStatement返回始终为空的记录集   java将无符号类型写入Netty ChannelBuffer   java动态资源名称   java lookupDefaultPrintService()不返回系统默认打印机   java如何在播放模板中翻译#{get'title'/}?   java为什么JSR352的ItemWriter接口中有一个checkpointInfo?有任何示例实现吗?   在方法外部声明的Java引用变量存在于堆栈或堆上   java类、异常、用户输入   java JApplet通过Eclipse而不是web浏览器连接到本地主机Mysql   java soap metro转储