位置: 编程技术 - 正文

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

  • 个税手续费返还政策最新规定2023
  • 银行的记账凭证怎么做
  • 应付账款赊销率和周转率的区别
  • 银行日记账的登记实例图
  • 资本公积什么情况下转增资本
  • 已勾选未认证什么意思
  • 代员工缴纳的个税放什么科目
  • 出口退税企业退税时间
  • 企业国有资产无偿划转办法
  • 应交增值税转入其他流动资产
  • 收到对方开错的发票怎么处理
  • 车辆保险怎么计算器
  • 个税返还奖励财务人员申报个税
  • 房屋租赁发票能抵扣几个点
  • 企业报社保可以用医保吗
  • 外管证开了未用怎么办
  • 盐酸编号
  • 如何处理走逃失的人
  • 医疗服务收入占比分析
  • 计提坏账准备需要什么附件
  • 未取得全额发票怎么处理
  • 个人开发票给公司需要提交哪些资料
  • 小规模减半征收什么时候开始
  • 票据质押后如何行使质权
  • 未做账务处理
  • 同一年可以先娶后嫁吗
  • 税前净利润等于什么
  • 外贸企业出口货物
  • 汇率调整怎么做分录
  • 宽带错误797最简单解决方法
  • linux中gedit命令
  • 企业自建自用房的规定
  • php escapeshellarg
  • 小规模纳税人的企业所得税税率
  • Win11 Build 22449.1000 预览版发布(附更新修复已知问题汇总)
  • layuiadmin动态菜单
  • 移民美国怎样加入医疗保险
  • 补充养老保险和养老保险的区别
  • 股权转让怎么做帐务处理
  • yolov1训练过程
  • phalcon model在插入或更新时会自动验证非空字段的解决办法
  • yum命令详解
  • 费用科目在贷方表示
  • 对公账户名称可以是个人名字吗
  • 出售无形资产净收益计入什么科目
  • 经营活动现金净流量为正说明什么
  • 销售成本包括销售人员工资吗
  • 固定资产清理净残值怎么处理
  • 土增尾盘销售应该如何申报收入
  • sql server 2008 怎么使用
  • 车出险理赔需要什么材料
  • 企业拆迁补偿款
  • 工程结算在资产中的作用
  • 一般纳税人购买原材料会计分录
  • 收到托收凭证怎么做分录
  • 多交的应交税费资产负债表怎么填
  • 股权支付费用是什么意思
  • 公司购买的礼品卡怎么做账
  • 工程材料增值税税率是多少
  • 跨境汇款汇错
  • 高新技术企业享受优惠时间
  • mysql数据库sid
  • sql server 2012 数据库bak脚本还原
  • mysql Access denied for user ‘root’@’localhost’ (using password: YES)解决方法
  • ubuntu mysql 5.6版本的删除/安装/编码配置文件配置
  • service.exe是什么
  • win8.1安装更新卡住
  • win7怎么调图片大小
  • cocos2d怎么创建项目
  • 将jquery.qqFace.js表情转换成微信的字符码
  • java的匿名内部类
  • 如何用虚拟号码打电话
  • 解决问题
  • js每天的定时任务
  • js正则检验手机号
  • JavaScript焦点事件、鼠标事件和滚轮事件使用详解
  • js文件保存
  • androidsdk的计算机
  • 怎么查询企业的联系方式
  • 公司加油卡充值需要带什么
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设