非字符串正则表达式,使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 LineNumberReader。如果查询行为不正确,则返回readLine()   java包含了一个使用AndroidX的工具栏,这让我的应用程序崩溃了   JVM设置通过“java jar”运行应用程序的最佳实践   java如何获取ImageButton宽度   java Oracle SQLLDR实用程序无响应   列出Java获取对象的arrayList中最常见的元素   java使用带有FlowLayout的getContentpane对布局应用更改,但不起作用为什么?   在java中,我可以在画布上绘制画布吗?   编译游戏代码时发生java异常错误   从firestore获取java Webview失败   java将TableLayout中单元格的内容向右对齐   java无法在发布模式下启动活动(使用proguard安卓optimize配置)   java允许在线程期间进行GUI更新。睡觉   java如何对以变量为列表的列表进行排序   API URL上的java Google云端点异常