位置: 编程技术 - 正文

XRegExp 0.2: Now With Named Capture

编辑:rootadmin

Update: A beta version of XRegExp 0.3 is now available as part of the RegexPal download package.

JavaScript's regular expression flavor doesn't support named capture. Well, says who? XRegExp 0.2 brings named capture support, along with several other new features. But first of all, if you haven't seen the previous version, make sure to check out my post on XRegExp 0.1, because not all of the documentation is repeated below.

HighlightsComprehensive named capture support (New) Supports regex literals through the addFlags method (New) Free-spacing and comments mode (x) Dot matches all mode (s) Several other minor improvements over v0.1 Named capture

There are several different syntaxes in the wild for named capture. I've compiled the following table based on my understanding of the regex support of the libraries in question. XRegExp's syntax is included at the top.

LibraryCaptureBackreferenceIn replacementStored atXRegExp(<name>…)k<name>${name}result.name.NET(?<name>…) (?'name'…) k<name> k'name' ${name}Matcher.Groups('name')Perl 5. (beta)(?<name>…) (?'name'…) k<name> k'name' g{name} $+{name}??Python(?P<name>…)(?P=name)g<name>result.group('name')PHP preg (PCRE)(.NET, Perl, and Python styles)$regs['name']$result['name']

No other major regex library currently supports named capture, although the JGsoft engine (used by products like RegexBuddy) supports both .NET and Python syntax. XRegExp does not use a question mark at the beginning of a named capturing group because that would prevent it from being used in regex literals (JavaScript would immediately throw an "invalid quantifier" error).

XRegExp supports named capture on an on-request basis. You can add named capture support to any regex though the use of the new "k" flag. This is done for compatibility reasons and to ensure that regex compilation time remains as fast as possible in all situations.

Following are several examples of using named capture:

// Add named capture support using the XRegExp constructorvar repeatedWords = new XRegExp("\b (<word> \w+ ) \s+ \k<word> \b", "gixk");// Add named capture support using RegExp, after overriding the native constructorXRegExp.overrideNative();var repeatedWords = new RegExp("\b (<word> \w+ ) \s+ \k<word> \b", "gixk");// Add named capture support to a regex literalvar repeatedWords = /b (<word> w+ ) s+ k<word> b/.addFlags("gixk");var data = "The the test data.";// Check if data contains repeated wordsvar hasDuplicates = repeatedWords.test(data);// hasDuplicates: true// Use the regex to remove repeated wordsvar output = data.replace(repeatedWords, "${word}");// output: "The test data."

In the above code, I've also used the x flag provided by XRegExp, to improve readability. Note that the addFlags method can be called multiple times on the same regex (e.g., /pattern/g.addFlags("k").addFlags("s")), but I'd recommend adding all flags in one shot, for efficiency.

Here are a few more examples of using named capture, with an overly simplistic URL-matching regex (for comprehensive URL parsing, see parseUri):

var url = " urlParser = new XRegExp("^(<protocol>[^:/?]+)://(<host>[^/?]*)(<path>[^?]*)\?(<query>.*)", "k");var parts = urlParser.exec(url);/* The result:parts.protocol: "http"parts.host: "microsoft.com"parts.path: "/path/to/file"parts.query: "q=1" */// Named backreferences are also available in replace() callback functions as properties of the first argumentvar newUrl = url.replace(urlParser, function(match){return match.replace(match.host, "yahoo.com");});// newUrl: " that XRegExp's named capture functionality does not support deprecated JavaScript features including the lastMatch property of the global RegExp object and the RegExp.prototype.compile() method.

Singleline (s) and extended (x) modes

The other non-native flags XRegExp supports are s (singleline) for "dot matches all" mode, and x (extended) for "free-spacing and comments" mode. For full details about these modifiers, see the FAQ in my XRegExp 0.1 post. However, one difference from the previous version is that XRegExp 0.2, when using the x flag, now allows whitespace between a regex token and its quantifier (quantifiers are, e.g., +, *?, or {1,3}). Although the previous version's handling/limitation in this regard was documented, it was atypical compared to other regex libraries. This has been fixed.

The code/* XRegExp 0.2.2; MIT LicenseBy Steven Levithan < support for the following regular expression features:- Free-spacing and comments ("x" flag)- Dot matches all ("s" flag)- Named capture ("k" flag) - Capture: (<name>...) - Backreference: k<name> - In replacement: ${name} - Stored at: result.name*//* Protect this from running more than once, which would break its references to native functions */if (window.XRegExp === undefined) {var XRegExp;(function () {var native = {RegExp: RegExp,exec: RegExp.prototype.exec,match: String.prototype.match,replace: String.prototype.replace};XRegExp = function (pattern, flags) {return native.RegExp(pattern).addFlags(flags);};RegExp.prototype.addFlags = function (flags) {var pattern = this.source,useNamedCapture = false,re = XRegExp._re;flags = (flags || "") + native.replace.call(this.toString(), /^[Ss]+//, "");if (flags.indexOf("x") > -1) {pattern = native.replace.call(pattern, re.extended, function ($0, $1, $2) {return $1 ? ($2 ? $2 : "(?:)") : $0;});}if (flags.indexOf("k") > -1) {var captureNames = [];pattern = native.replace.call(pattern, re.capturingGroup, function ($0, $1) {if (/^((?!?)/.test($0)) {if ($1) useNamedCapture = true;captureNames.push($1 || null);return "(";} else {return $0;}});if (useNamedCapture) {/* Replace named with numbered backreferences */pattern = native.replace.call(pattern, re.namedBackreference, function ($0, $1, $2) {var index = $1 ? captureNames.indexOf($1) : -1;return index > -1 ? "\" + (index + 1).toString() + ($2 ? "(?:)" + $2 : "") : $0;});}}/* If "]" is the leading character in a character class, replace it with "]" for consistentcross-browser handling. This is needed to maintain correctness without the aid of browser sniffingwhen constructing the regexes which deal with character classes. They treat a leading "]" within acharacter class as a non-terminating, literal character, which is consistent with IE, .NET, Perl,PCRE, Python, Ruby, JGsoft, and most other regex engines. */pattern = native.replace.call(pattern, re.characterClass, function ($0, $1) {/* This second regex is only run when a leading "]" exists in the character class */return $1 ? native.replace.call($0, /^([^?)]/, "$1\]") : $0;});if (flags.indexOf("s") > -1) {pattern = native.replace.call(pattern, re.singleline, function ($0) {return $0 === "." ? "[\S\s]" : $0;});}var regex = native.RegExp(pattern, native.replace.call(flags, /[sxk]+/g, ""));if (useNamedCapture) {regex._captureNames = captureNames;/* Preserve capture names if adding flags to a regex which has already run through addFlags("k") */} else if (this._captureNames) {regex._captureNames = this._captureNames.valueOf();}return regex;};String.prototype.replace = function (search, replacement) {/* If search is not a regex which uses named capturing groups, just run the native replace method */if (!(search instanceof native.RegExp && search._captureNames)) {return native.replace.apply(this, arguments);}if (typeof replacement === "function") {return native.replace.call(this, search, function () {/* Convert arguments[0] from a string primitive to a string object which can store properties */arguments[0] = new String(arguments[0]);/* Store named backreferences on the first argument before calling replacement */for (var i = 0; i < search._captureNames.length; i++) {if (search._captureNames[i]) arguments[0][search._captureNames[i]] = arguments[i + 1];}return replacement.apply(window, arguments);});} else {return native.replace.call(this, search, function () {var args = arguments;return native.replace.call(replacement, XRegExp._re.replacementVariable, function ($0, $1, $2) {/* Numbered backreference or special variable */if ($1) {switch ($1) {case "$": return "$";case "&": return args[0];case "`": return args[args.length - 1].substring(0, args[args.length - 2]);case "'": return args[args.length - 1].substring(args[args.length - 2] + args[0].length);/* Numbered backreference */default:/* What does "$" mean?- Backreference , if at least capturing groups exist- Backreference 1 followed by "0", if at least one capturing group exists- Else, it's the string "$" */var literalNumbers = "";$1 = +$1; /* Cheap type-conversion */while ($1 > search._captureNames.length) {literalNumbers = $1.toString().match(/d$/)[0] + literalNumbers;$1 = Math.floor($1 / ); /* Drop the last digit */}return ($1 ? args[$1] : "$") + literalNumbers;}/* Named backreference */} else if ($2) {/* What does "${name}" mean?- Backreference to named capture "name", if it exists- Else, it's the string "${name}" */var index = search._captureNames.indexOf($2);return index > -1 ? args[index + 1] : $0;} else {return $0;}});});}};RegExp.prototype.exec = function (str) {var result = native.exec.call(this, str);if (!(this._captureNames && result && result.length > 1)) return result;for (var i = 1; i < result.length; i++) {var name = this._captureNames[i - 1];if (name) result[name] = result[i];}return result;};String.prototype.match = function (regexp) {if (!regexp._captureNames || regexp.global) return native.match.call(this, regexp);return regexp.exec(this);};})();}/* Regex syntax parsing with support for escapings, character classes, and various other context and cross-browser issues */XRegExp._re = {extended: /(?:[^[#s\]+|\(?:[Ss]|$)|[^?]?(?:[^\]]+|\(?:[Ss]|$))*]?)+|(s*#[^nr]*s*|s+)([?*+]|{d+(?:,d*)?})?/g,singleline: /(?:[^[\.]+|\(?:[Ss]|$)|[^?]?(?:[^\]]+|\(?:[Ss]|$))*]?)+|./g,characterClass: /(?:[^\[]+|\(?:[Ss]|$))+|[^?(]?)(?:[^\]]+|\(?:[Ss]|$))*]?/g,capturingGroup: /(?:[^[(\]+|\(?:[Ss]|$)|[^?]?(?:[^\]]+|\(?:[Ss]|$))*]?|((?=?))+|((?:<([$w]+)>)?/g,namedBackreference: /(?:[^\[]+|\(?:[^k]|$)|[^?]?(?:[^\]]+|\(?:[Ss]|$))*]?|\k(?!<[$w]+>))+|\k<([$w]+)>(d*)/g,replacementVariable: /(?:[^$]+|$(?![1-9$&`']|{[$w]+}))+|$(?:([1-9]d*|[$&`'])|{([$w]+)})/g};XRegExp.overrideNative = function () {/* Override the global RegExp constructor/object with the XRegExp constructor. This precludes accessingproperties of the last match via the global RegExp object. However, those properties are deprecated asof JavaScript 1.5, and the values are available on RegExp instances or via RegExp/String methods. It alsoaffects the result of (/x/.constructor == RegExp) and (/x/ instanceof RegExp), so use with caution. */RegExp = XRegExp;};/* indexOf method from Mootools 1.; MIT License */Array.prototype.indexOf = Array.prototype.indexOf || function (item, from) {var len = this.length;for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++) {if (this[i] === item) return i;}return -1;};

You can download it, or get the packed version (2.7 KB).

XRegExp has been tested in IE 5.5?7, Firefox 2.0.0.4, Opera 9., Safari 3.0.2 beta for Windows, and Swift 0.2.

Finally, note that the XRE object from v0.1 has been removed. XRegExp now only creates one global variable: XRegExp. To permanently override the native RegExp constructor/object, you can now run XRegExp.overrideNative();

推荐整理分享XRegExp 0.2: Now With Named Capture,希望有所帮助,仅作参考,欢迎阅读内容。

XRegExp 0.2: Now With Named Capture

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

CLASS_CONFUSION JS混淆 全源码 利用随机字符串代替变量等,混淆原代码,保护自己写的代码,不利于别人直接剽窃SCRIPTlanguage=JavaScript!--/**//**//**//****============================================

mapper--图片热点区域高亮组件官方站点 很有意思的一个东西,我们都用过图片热点对多个切片做链接,也用过链接的hover高亮效果,但却没有办法实现图片热点的高亮效果(即鼠标悬停在某

DOMAssitant最新版 DOMAssistant 2.5发布 一个googlecode上的project刚发布了2.5版号称又要做一个大而全的js的库,要和jQuery,prototype,YUI,Ext对抗的,哈哈WiththisreleaseofDOMAssistant,Ifeelthatitcanseriouslycompetew

标签: XRegExp 0.2: Now With Named Capture

本文链接地址:https://www.jiuchutong.com/biancheng/386441.html 转载请保留说明!

上一篇:js定义对象简单学习例子(js中定义对象)

下一篇:CLASS_CONFUSION JS混淆 全源码

  • 外部奖励与内部奖励
  • 预缴税款可以抵税吗
  • 公司废料收入如何分配
  • 没有上市的公司怎么看财务报表
  • 电子承兑对方拒绝签收
  • 银行日记账的登记实例图
  • 党费帐常用会计分录
  • 收到的其他与筹资活动有关的现金包括
  • 新准则下怎么调整长期股权投资损益调整
  • 因管理不善的材料盘亏如何做账
  • 发票折扣有没有限制
  • 行政单位发放的政府补贴款
  • 税友的票可以抵扣吗?
  • 加权投资年限怎么计算
  • 股东垫支开办费
  • 给别人的返利是属于什么费用
  • 打开我的电脑提示该文件没有与之
  • 税务自查补税后还有风险吗
  • 个人所得税如何退税操作步骤
  • h5实现扫码功能
  • 苹果 macOS 13.3 开发者预览版 Beta 2 发布
  • 资金运动包括哪几个方面
  • 表单的基本语法格式
  • 进项税额是
  • php封装app
  • 投资性房地产出售时其他综合收益
  • php socket编程
  • ValueError: The device should not be ‘gpu‘, since PaddlePaddle is not compiled with CUDA问题解决(Paddle)
  • 公司与公司的往来款清帐需要交税吗
  • 费用报销单怎样粘贴
  • lstm crf
  • apk文件包下载
  • map获取entry
  • 淘宝运费险费用很高
  • 公司多余的钱叫什么
  • 织梦专题页模板
  • mongodb $sum
  • 购办公桌椅入什么费用
  • 货代一般一个柜利润多少
  • 不开增值税发票的销售收入报税的操作流程是?
  • MongoDB中MapReduce编程模型使用实例
  • 商品组装后出售怎么做账
  • 收到股东投资款需要交印花税吗
  • 制造费用科目一定无余额
  • 分期收款发出商品是什么意思
  • 收到银行开的手续费发票如何做帐
  • 实际出资大于注册资金
  • 诉讼费可以退回私账嘛
  • 融资租入固定资产的入账价值
  • 来料加工账务处理案例
  • 库存商品视频讲解
  • 溢价发行股票的交易费用
  • sql server browser被禁用
  • sqlserver数据库显示单个用户
  • mysql数据库子查询
  • 找回被删除的文件时第一步应该是什么
  • linux几种安装方式
  • ubuntu20.04最小化安装教程
  • centos文件备份
  • win10系统edge浏览器兼容性
  • win8粘贴板
  • 如何管理和维护宿舍卫生
  • shell脚本通过expect实现自动单边无密登录功能
  • perl $?
  • jquery 插件写法
  • 相片管理必备知识
  • Android AsyncTask简要分析
  • js数组如何定义
  • android 属性动画改变view大小
  • android使用so
  • unity移动脚本代码
  • js设计模式和开发实践
  • javascript零基础入门
  • 猫的游戏视频
  • 深圳12366怎么转人工
  • 河南省地方税务局公告2017年第4号
  • 怎么绑定办税员
  • 浙江税务开票系统
  • 初级会计职称可以挂靠吗
  • 杭州 国税
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设