位置: 编程技术 - 正文

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混淆 全源码

  • 现金流量表填报说明
  • 外购软件用于销售的会计分录
  • 房地产中心
  • 死账呆账的处理程序
  • 公司清算后资产负债表与利润表
  • 不同外币之间的折算
  • 创投资本投入资金如何做账?
  • 房地产预交税金及附加要计提吗
  • 加油的时候可以开发票吗
  • 收到去年未计提折旧费
  • 箱包类增值税发票多少点
  • 一般纳税人开专票和普票的税率
  • 房地产母公司将其土地变更到其全资子公司
  • 开汽车租赁发票需要什么资料?
  • 财政返还政策
  • 土地增值税计算表
  • 营增改的四大“增效剂”
  • 公司注销欠法人款怎么帐务处理?
  • 招商引资政府返税政策不兑现
  • 往年银行余额和账目不符怎么调整
  • 固定资产折现率怎么算
  • 应交税费核算
  • 退回社保费的会议记录
  • 认缴出资日期是2050什么意思
  • 农民工劳动报酬权救济制度存在的问题
  • linux系统情况
  • mac怎么卸载软件core sync
  • 网关设置
  • win10怎么打开移动中心
  • 未分配利润进行利润分配分录
  • 发票已到货未到会计处理
  • 职工教育经费超过扣除限额的时候调增还是调减
  • 个人通讯费可以税前扣除吗
  • php运用
  • framework7教程
  • php中哪个命令用来删除当前目录
  • 存货捐赠视同销售要不要确认收入?
  • 原生js实现promise.all
  • php session用法
  • php 截断
  • 管理费用科目核算的内容
  • 电子发票是正规发票吗能报销吗
  • 保理融资费用账务处理
  • 劳务派遣工资是死的吗
  • 增值税纳税申报实训报告
  • 税局代个人开增值税普通票样板
  • 税费计提多了怎么冲减
  • 税控盘 金税盘
  • 个体工商户增值税申报操作流程
  • 接受捐赠计入
  • 劳务费如何开票给客户
  • 违约金 专票
  • 土地使用税的账务处理分录
  • 企业变更地址需要几天
  • 待认证进项税怎么转出
  • 支付大型设备税率是多少
  • 待摊费用年底能够有余额么
  • 对公账户与私人账户都是一级
  • 公司没开户需要做账吗怎么做
  • 出纳提取现金的业务流程
  • window10 左下角
  • win10一年更新一次
  • windows设置tomcat自动重启
  • zmweb.exe是什么进程
  • 如何清楚windows搜索记录
  • linux中docker
  • 服务器不支持是什么意思
  • win7系统网速太慢怎么办
  • WIN7系统的镜像文件在哪里
  • bootstrap技术教程
  • Nodejs sublime text 3安装与配置
  • 加快构建新发展格局,着力推动高质量发展心得体会
  • 菜鸟app兼职
  • IE、FF、Chrome浏览器中的JS差异介绍
  • 关于中秋节的古诗
  • python的threadpool
  • javascript 进阶篇2 CSS XML学习
  • 代扣代缴申报表哪里查询
  • 国税总局商品编码是什么
  • 低保户系统能查出来吗
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设