非字符串正则表达式,使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 Rest DSL路由无法启动路由,因为同一端点不允许有多个使用者   jvm有没有像JConsole或VisualVM这样的工具可以告诉我“类、对象、引用变量在java中存储在哪里?”   java为什么我的列表中的所有元素看起来都一样?   java运行时。运行shell脚本的exec无法打开文件   JPopupMenu的JMenuItem的java热键   会话在Java中被覆盖   如何在java中去除字符串中的尖锐重音?   java Mockito监视一个接口,模拟它的默认方法,获取NullPointerException   javascript如何在jquery中禁用同一时间选择   将数组列表附加到现有CSV文件,但它会附加并清除存储在Java文件中的以前的数据   java从我的jar中访问pdf文件   java Sonar issue参数必须为非Null,但标记为可为Null   java Salesforce流式API:在网络故障之后和重新订阅之前获取事件   在Java 1.8.0_65上运行Play2.0应用程序时出现playframework错误   java为什么字母的ASCII由方法自动转换。toCharArray()?   java如何知道JDialog是否关闭?   java向服务器发送POST请求,服务器的响应为null,启动   java如何设置JTable中特定单元格的值?   ImagePlus中的java保存问题