糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > apg 代码_正则表达式的替代方法:apg-exp

apg 代码_正则表达式的替代方法:apg-exp

时间:2020-01-28 07:37:37

相关推荐

apg 代码_正则表达式的替代方法:apg-exp

apg 代码

Sebastian Seitz和Almir Bijedic对此文章进行了同行评审。感谢所有SitePoint的同行评审员使SitePoint内容达到最佳状态!

几乎没有程序员会时不时使用一种形式或另一种形式使用正则表达式 。 对于许多人来说,模式语法似乎是晦涩难懂的。 本教程将介绍一个新的模式匹配引擎apg-exp,它是RegExp的功能丰富的替代方案,具有ABNF模式语法,在外观上更容易一些。

快速比较

您是否曾经需要验证电子邮件地址并遇到类似这样的问题?

^[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$

模式匹配引擎是完成此任务的正确工具。 这是一个设计良好,编写良好的正则表达式。 效果很好。 那不喜欢什么?

好吧,如果您是一位具有正则表达式的专家,那么什么都没有。 但是对于我们其他人来说,

难以阅读 更难写 难以维护

正则表达式语法具有悠久的历史,并且已深深地集成到我们作为程序员每天使用的许多工具和语言中。

但是,有一种替代语法已经存在了很长时间,它在Internet技术规范的作者和用户中非常流行,具有正则表达式的所有功能,但在JavaScript编程领域很少使用。 即,在Augmentedackus-ÑAUR˚FORM,或ABNF,由正式定义IETF在RFC 5234和RFC 7405 。

让我们看看在ABNF中相同的电子邮件地址可能是什么样。

email-address = local "@" domainlocal = local-word *("." local-word)domain= 1*(sub-domain ".") top-domainlocal-word= 1*local-charsub-domain= 1*sub-domain-chartop-domain= 2*6top-domain-charlocal-char= alpha / num / specialsub-domain-char = alpha / num / "-"top-domain-char = alphaalpha = %d65-90 / %d97-122num = %d48-57special = %d33 / %d35 / %d36-39 / %d42-43 / %d45 / %d47 / %d61 / %d63 / %d94-96 / %d123-126

当然,它并不那么紧凑,但是它像HTML和XML一样,被人类和机器读取。 我猜想,除了对通配符搜索模式的了解以外,您还可以用“普通英语”阅读这里发生的事情。

电子邮件地址定义为本地部分和以@分隔的域 本地部分是一个单词,后跟可选的以点分隔的单词 域是一个或多个点分隔的子域,后跟一个顶部域 您在这里可能不知道,但可能可以猜测的唯一的事情是: 就像通配符*表示“零个或多个”,1*表示“一个或多个”和2*6表示最少2次重复和最多6次重复/分隔其他选择%d定义十进制字符代码和字符代码范围 例如,%d35代表#,ASCII十进制35%d65-90代表AZ范围内的任何字符,ASCII小数点65-90

在示例1中将RegExp和apg-exp与此电子邮件地址进行比较。

apg-exp是一种模式匹配引擎,旨在具有RegExp的外观,但使用ABNF语法进行模式定义。 在接下来的几节中,我将指导您完成:

如何让apg-exp进入您的应用 ABNF语法的简要指南 使用apg-exp-一些示例 接下来要去哪里—更多详细信息,高级示例

启动并运行-如何获取它

npm

如果您在Node.js环境中工作,请从您的项目目录运行:

npm install apg-exp --save

然后,您可以使用require()在代码中访问它。

例如:

var ApgExp = require("apg-exp");var exp = new ApgExp(pattern, flags);var result = exp.exec(stringToMatch);

的GitHub

要从GitHub获取代码的副本,您可以将存储库克隆到您的项目目录中:

git clone /ldthomas/apg-js2-exp.git apg-exp

或将其下载为zip文件 。

然后在page.html

<!-- optional stylesheet used in tutorial examples --><link rel="stylesheet" href="./apg-exp/apgexp.css"><script src="./apg-exp/apgexp-min.js"></script><script>var useApgExp = function(){var exp = new ApgExp(pattern, flags); var result = exp.exec(stringToMatch);/* do something with the result */}</script>

CDN

您还可以使用RawGit直接从GitHub源创建CDN版本。 但是,请务必阅读无正常运行时间或支持保证 (实际上,请务必阅读完整的FAQ )。

本教程的所有示例均使用以下内容。

<link rel="stylesheet"href="/ldthomas/apg-js2-exp/89c6681798ba9e47583b685c87b244406b18a26d/apgexp.css"><scriptsrc="/ldthomas/apg-js2-exp/c0fc3adac954a6f6ad6f265fd2f8f06f68001e10/apgexp-min.js"charset="utf-8"></script>

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95您的完全免费

这些文件被缓存在MaxCDN服务器上,只要它们仍然可用,您就可以随意使用它们进行测试。 但是,对于生产而言,应将apgexp-min.jsapgexp.css副本apgexp.css在您自己的服务器上,以确保访问

并将它们包含在您的页面中,使其最适合您的应用程序。

ABNF简要指南

ABNF是描述短语的语法,短语可以是任何字符串。 如您在上面的电子邮件示例中所看到的,它使您可以将复杂的短语分解为更简单的短语的集合。 短语定义的形式为:

name = elements LF

其中LF是换行符(换行符\n)。

下表是这些元素的简要指南(完整指南请参见SABNF )。

注意1:规则名称必须在该行的第一列中以字母字符开头。 续行必须以空格或制表符开头。 第一条规则定义了要匹配的整个短语或模式。 以下规则定义了整个短语中的命名子短语(或命名捕获)。

注2:重复的一般形式是n*m,定义了最少n重复和最大m重复。 简写符号可以是*m表示零到mn*表示n到无穷大,也可以只是n表示n*n

注意3:分组对于保持交替和串联行为符合预期非常重要。 串联比交替具有更严格的绑定。 如果

phrase1 = elem (foo / bar) blat LFphrase2 = (elem foo) / (bar blat) LFphrase3 = elem foo / bar blat LF

然后,phrase1elem foo blatelem bar blat匹配,而phrase2phrase3elem foobar blat匹配。 小心并自由使用分组。

使用apg-exp-几个例子

现在,您的应用程序中已包含apg-exp,并且了解编写模式语法的基础知识,让我们直接进入有趣的部分,并查看一些如何使用它的示例。

在下面的下一节中,我将构造对象的无聊细节放入。 您可以根据需要参考它以理解示例。 我还将跳过错误处理,但您应该意识到,如果存在模式错误,构造函数将抛出ApgExpError异常对象,该对象具有几个方便的函数,用于格式化显示模式错误。 您的try/catch块可能看起来像这样:

try {var exp = new ApgExp(pattern, flags);var result = exp.exec(stringToMatch);if (result) {// do something with results} else {// handle failure}} catch(e) {if (e.name === "ApgExpError") {// display pattern errors to consoleconsole.log(e.toText());// display pattern errors to HTML page$("#errors").html(e.toHtml());} else {// handle other exceptions}}

电话号码

电话号码是一个常见的表单验证问题,也是介绍一些基本知识的好机会。 通常,您只想知道以类似于电话号码的形式输入了10位数字,而不必担心北美计划或国际号码的详细信息。

我们只要求它以圆括号(或一个数字)开头,并包含3、3和4个数字的块,由0到3个非数字分隔。这足以接受最常见的格式,并且足以捕获该区域,办公室和订户代码作为任何重新格式化的捕获组。

这是ABNF中的样子:

phone-number = ["("] area-code sep office-code sep subscriberarea-code = 3digit ; 3 digitsoffice-code = 3digit ; 3 digitssubscriber = 4digit ; 4 digitssep= *3(%d32-47 / %d58-126 / %d9) ; 0-3 ASCII non-digitsdigit = %d48-57 ; 0-9

示例2演示了这一点,并为您提供了更改电话号码格式的机会:

示例3让我们使用模式语法,看看您可能希望看到的错误消息:

RegExp语法,

\(?(\d{3})\D{0,3}(\d{3})\D{0,3}(\d{4})

也不难, 示例4进行了并排比较。

日期

现在让我们稍微增加一下,看看匹配日期时apg-exp和RegExp的比较。

我们的日期格式要求是:

mm/dd/yy or mm/dd/yyyydd/mm/yy or dd/mm/yyyymm, 1-12 or 01-12, i.e. with or without leading zerodd, 1-31 or 01-31, i.e. with or without leading zeroyy, 00-99yyyy, 1900-1999 or 2000-2099

mm/dd/yyyy格式本身并不那么困难,但是限制数字范围才是提高格式的原因。 使用ABNF到达那里看起来像这样:

date= %^ (mm-first / dd-first) %$mm-first = mm "/" dd "/" yyyy ; month before daydd-first = dd "/" mm "/" yyyy ; day before monthdd = "0" digit1 ; 01-09/ ("1"/"2") digit; or 10-29/ "3" %d48-49; or 30-31/ digit1; or 1-9mm = "0" digit1 ; 01-09/ "1" %d48-50; or 10-12/ digit1; or 1-9yyyy= ("19" / "20") 2digit ; 1900-1999 or 2000-2099/ 2digit; or 00-99digit = %d48-57 ; 0-9digit1 = %d49-57 ; 1-9

评论使它很不言自明。 请注意,ddmmyyyy具有最短的替代项。 这一点非常重要,因为apg-exp总是采用“首场比赛获胜”的方法来替代。 从左到右尝试替代项,一旦找到匹配项,将忽略所有剩余的替代项。 在这里,这意味着当一个模式可以匹配一位或两位数字时,两位数模式必须是第一位。

按照与上述完全相同的方法,将日期分为ddmm[yy]yy备用模式,然后将它们组合为完整日期,将产生以下RegExp语法:

^(?:((?:0[1-9])|(?:1[0-2])|(?:[1-9]))/((?:0[1-9])|(?:(?:1|2)[0-9])|(?:3[0-1])|(?:[1-9]))|((?:0[1-9])|(?:(?:1|2)[0-9])|(?:3[0-1])|(?:[1-9]))/((?:0[1-9])|(?:1[0-2])|(?:[1-9])))/((?:19|20)?[0-9][0-9])$

我不是RegExp专家,因此可能有一些方法可以缩短此时间,但是此方法可以工作。 您可以在示例5中进行比较。 跳到那边做一下。

使用递归匹配嵌套对(())

最后,我想展示如何匹配括号对,括号等的嵌套对。 尽管这是一个非常重要的模式匹配问题,但是RegExp无法做到。 对于匹配的括号对,请考虑以下ABNF:

P = L P R / L RL = "("R = ")"

请注意,规则P出现在其自己的定义中。 这称为递归。 尽管某些类型的正则表达式引擎确实支持递归,而某些RegExp工具确实提供了递归功能,但是JavaScript的RegExp根本不支持递归。 上面的LR已选择匹配括号,但只要LR不能匹配相同,它们就可以是任何东西。

转到示例6 ,我们将在递归中获得一些乐趣。

在离开匹配的嵌套对这一主题之前,我想演示一些实际的示例,apg-exp可以帮助您。

在示例6中,您看到了如何在对中匹配对并在方括号之间包含文本。 假设您的任务是编写一个程序,使得:如果光标位于大括号{,突出显示匹配的大括号}

示例7向您显示了此问题的解决方案。 您将需要了解sticky模式。

最后一个嵌套对示例。 您是否曾经想过注释掉一个很大HTML块,只是发现该块中已经有注释了? 令人沮丧吗? 只需在Internet上搜索“ HTML嵌套注释问题”,便会感到沮丧。 示例8为您显示了解决此问题的一种可能的方法。警告-这可能会使您有些紧张。 您将需要了解result.rules对象和global模式。

汇集全部

总结一下,让我们看看完整的表单验证示例的外观。

通常,在创建新帐户时,会要求您输入用户名,电子邮件地址,密码和密码确认。 我们要求用户名是3-32个ASCII字母,连字符和句点。 密码必须为8-16个大写字母,小写字母或数字,并且每个密码中至少有一个。

在继续之前,该表格将在任何无效条目上方显示一个描述性错误消息。 示例9将所有内容组合在一起。

见钢笔APG-EXP:一个正则表达式的替代:实施例9通过SitePoint( @SitePoint )上CodePen 。

库API

我试图在本节中提供足够的信息来理解上面的示例。 但是,有许多高级功能需要对解析理论进行更深入的了解才能使用,而我刚刚对那些功能进行了“高级”注释。

输入参数

apg-exp构造函数ApgExp最多包含四个参数。

var exp = new ApgExp(pattern[, flags[, nodeHits[, treeDepth]]]);

模式 字符串:如上一节所述的SABNF模式语法*。 对象:实例化的APG解析器对象。 (高级选项。) 标志:字符串:任何字符"gyud"g –全局模式:迭代所有模式匹配(请参见示例8 ) y –粘性模式:将匹配项固定在exp.lastIndex(请参见示例7 ) u – Unicode模式:以整数字符代码而不是字符串的数组形式返回结果 d –调试模式:高级选项–公开APG跟踪对象 nodeHits:整数> 0:默认=Infinity:将匹配算法限制为"nodeHits"步骤。 防止灾难性的回溯。 treeDepth:整数> 0:默认值=Infinity:限制匹配的解析器的树深度。

*例如,要匹配字母数字名称,可以使用输入字符串:

var pattern = "alphanum = alpha *(alpha / num)\n"+ "alpha = %d65-90 / %d97-122\n"+ "num = %d48-57\n";

属性和方法

构造的对象exp本身具有16个属性和14个方法。

注1:如果unicode标志为true则它将是整数字符代码的数组,否则为字符串。

注2:用户可以自由将其设置为任何值。模式匹配始终从该索引值开始。尝试匹配后,它的使用和值受全局和粘性模式影响。参见示例7和8 。

结果对象

模式匹配成功后,将在具有7个属性和3个方法的result对象中返回结果:

var result = exp.exec(str);

注释3:例如,result.rules["name"][i] = {phrase: string/array, index: integer}参见示例8 。

下一步去哪里

我试图将其最小化,只是让您了解一下apg-exp库和ABNF的外观以及它们与RegExp的堆叠方式。 但是,您还有很多事情要做。 如果您想提高模式匹配技能,或者只是想冒险,请查看这些更高级的示例并参考完整的用户指南 。

我是否已说服您在下一个项目中尝试apg-exp? 您认为ABNF比正则表达式更容易使用吗? 我希望在下面的评论中收到您的来信!

翻译自: /alternative-to-regular-expressions/

apg 代码

如果觉得《apg 代码_正则表达式的替代方法:apg-exp》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。