位置: 编程技术 - 正文

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

  • 个税退付手续费是单位所得吗
  • 金税盘开票软件换电脑后怎么操作
  • 股东个人房产转入公司契税
  • 上缴非税收入前是否要交税
  • 有限公司能变更为个体工商户
  • 增值税的税目有哪些类型
  • 发票未到已验收什么意思
  • 开票个人账户的钱怎么查
  • 转让不动产取得的发票
  • 银行卡撤销账户
  • 年底没计提年终奖,下一年发放要怎么做
  • 超过保质期存储时间或变质的食品应该怎样处理
  • 出口转内销增值税报表怎么填
  • 工业企业电费出售会计分录怎么写?
  • 原材料做成库存会计分录
  • 商品房买卖合同预售和商品房买卖合同有什么区别
  • 免税单位取得增值税发票
  • 修理厂普通发票
  • 实时扣税3001会计科目
  • 增值税附表一免税项目金额填不上
  • 可以全额抵扣的发票
  • 承兑跨省是不是不能用
  • 主营业务收入少记跨年怎么办
  • 所有者权益变动表范本
  • 个人独资所得税税率表最新
  • 代收的税金如何记账
  • 编制合并报表的三种理论
  • php __destruct
  • 生产企业出口退税全部流程
  • 交易性金融资产的入账价值
  • 利息支出属于成本项目吗
  • linux的nano是什么意思
  • pytorch基础
  • 日期按钮
  • 小企业会计准则没有以前年度损益调整科目
  • 织梦怎么改文字
  • mysql in()
  • 差旅费单子格式表
  • mysql数据库性能优化方法有哪些
  • 货款未转到公司怎么处理
  • 失控发票要补交所得税吗
  • 企业营业执照的颁发部门是
  • 一般纳税人认定书是什么样子
  • 实收资本在核算上有哪些要求
  • 房地产开发企业资质证书
  • 增值税专票开具与发票专用章保管
  • 注册资金没显示
  • 出租房屋损坏赔偿
  • 事业单位发放生育津贴从哪年执行的
  • 新建厂房需要缴纳什么税
  • 财务费用包括什么项目
  • 微信收款怎样记账
  • 金税盘可以申请发票吗
  • 18年水利基金税率
  • 土地增值税计算题
  • 建筑业分包税收政策
  • 分页式存储管理中页的大小是可以不相等的
  • windows 9x
  • 未知文件怎么删除
  • 在幻灯片母版中
  • linux中tailf命令
  • windows7粘滞键怎么关
  • win10应用商店是灰的
  • 三种方法完美解决问题
  • Win10输入法切换快捷键改不了
  • windows8如何使用
  • pdf在电脑上打开
  • Win10 Mobile 10586.164上手体验视频评测
  • win8上不了网
  • unity做安卓app
  • node.js报错998
  • 一周总结家长寄语
  • 样式默认有几种修改格式
  • Linux命令行和shell脚本编程大全
  • 批处理命令显示内容
  • python编写api接口
  • 在javascript中如果不指明对象直接调用
  • 重庆电子税务局官网登录入口
  • 123600是税务电话吗
  • 再生资源税点
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设