?= ?: ?! 的理解及引用举例(数字格式化 1,123,000)

要理解?=和?!,首先需要理解 前瞻,后顾,负前瞻,负后顾四个概念:(有的管它叫零宽断言)

// 正向前瞻:
exp1(?=exp2) 查找exp2前面的exp1
// 正向后顾:
(?<=exp2)exp1 查找exp2后面的exp1
// 负向前瞻:
exp1(?!exp2) 查找后面不是exp2的exp1
// 负向后顾:
(?<!exp2)exp1 查找前面不是exp2的exp1

举例:

"中国人".replace(/(?<=中国)人/, "rr") // 匹配中国人中的人,将其替换为rr,结果为 中国rr
"法国人".replace(/(?<=中国)人/, "rr") // 结果为 法国人,因为人前面不是中国,所以无法匹配到

要理解?:则需要理解捕获分组和非捕获分组的概念:

() 表示捕获分组,() 会把每个分组里的匹配的值保存起来,使用 $n ( n 是一个数字,表示第 n 个捕获组的内容)
(?:) 表示非捕获分组,和捕获分组唯一的区别在于,非捕获分组匹配的值不会保存起来
举例:

‘adsaaa‘.match(/a(?:d|a)/g)  //  ["ad", "aa"]

?:的用处主要是在有|的时候,很好用,例如a(?:d|r)匹配的就是ad或者ar

?: 的应用 (数字格式化 1,123,000)

// 数字格式化 1,123,000
"1234567890".replace(/\B(?=(?:\d{3})+(?!\d))/g,",") // 结果:1,234,567,890,匹配的是后面是3*n个数字的非单词边界(\B)

不得不说正则真的很难读懂:

document.write("1234".replace(/\d(?=23)/g, "x"),`<br/>`) // "x234"    把 23 的前一个数字 替换成x
document.write("1234".replace(/(?=23)\d/g, "x"),`<br/>`) // "1x34"    把 23 的第一个数字 替换成x

document.write("1234".replace(/(?<=23)\d/g, "x"),`<br/>`) // "123x"   把 23 的后一个数字 替换成x
document.write("1234".replace(/\d(?<=23)/g, "x"),`<br/>`) // "12x4"   把 23 的最后一个数字 替换成x

document.write("1234".replace(/\d(?!23)/g, "x"),`<br/>`) // "1xxx"    把除了 23 的前一个数字之外的数字 替换成x
document.write("1234".replace(/(?!23)\d/g, "x"),`<br/>`) // "x2xx"    把除了 23 的第一个数字之外, 替换成x

document.write("1234".replace(/(?<!23)\d/g, "x"),`<br/>`) // "xxx4"   把除了 23 的后一个数字之外的数字 替换成x
document.write("1234".replace(/\d(?<!23)/g, "x"),`<br/>`) // "xx3x"   把除了 23 的最后一个数字之外, 替换成x

根据多次反复的试验,给出以上解释,但终究难知其所以然,若有大神可以指点迷津,万分感谢。

个人理解:

?= 正向前瞻  ?! 负向前瞻  ?<= 正向后顾  ?<! 负向后顾

我把上文中的 23 称之为 判断字符,将要找的那个字符 \d 称之为 查找字符

书写规范:①前瞻:查找字符 放在 分组 之前,②后顾:查找字符 放在 分组 之后。

符合上述4中情况且书写规范的情况下,查找字符 就是 判断字符 紧挨着的字符。

若书写顺序于规范相反,查找字符 则是 判断字符 中的字符。

const fn = (str) => {

// 匹配“范围是小写字母的任意字符”前面的数字,只匹配数字。

const a = /(?=.*[a-z])\d/

// 匹配“a-z范围内的字母”前面的数字,只匹配数字。

const b = /\d(?=[a-z])/

// 匹配“范围是小写字母的任意字符”后面的数字,只匹配数字。

const c = /(?<=.*[a-z])\d/

// 匹配“a-z范围内的字母”后面的数字,只匹配数字。

const d = /(?<=[a-z])\d/

return [a.test(str), b.test(str), c.test(str), d.test(str)]

}

console.log(fn("a23456")) // [false, false, true, true]

console.log(fn("2a3456")) // [true, true, true, true]

console.log(fn("23456a")) // [true, true, false, false]

原文地址:https://www.cnblogs.com/MrZhujl/p/12121164.html

时间: 2024-10-16 03:46:25

?= ?: ?! 的理解及引用举例(数字格式化 1,123,000)的相关文章

String.Format数字格式化输出 {0:N2} {0:D2} {0:C2} (转)

String.Format数字格式化输出 {0:N2} {0:D2} {0:C2} (转) //格式为sring输出 // Label1.Text = string.Format("asdfadsf{0}adsfasdf",a); // Label2.Text = "asdfadsf"+a.ToString()+"adsfasdf"; // Label1.Text = string.Format("asdfadsf{0:C}adsfas

String.Format数字格式化输出 {0:N2} {0:D2} {0:C2}

String.Format数字格式化输出 {0:N2} {0:D2} {0:C2} 数字 {0:N2} 12.36 数字 {0:N0} 13 货币 {0:c2} $12.36 货币 {0:c4} $12.3656 货币 "¥{0:N2}" ¥12.36 科学计数法 {0:E3} 1.23E+001 百分数 {0:P} 12.25% P and p present the same. 日期 {0:D} 2006年11月25日 日期 {0:d} 2006-11-25 日期 {0:f} 20

理解父类引用指向子类对象

java多态,如何理解父类引用指向子类对象 要理解多态性,首先要知道什么是“向上转型”. 我定义了一个子类Cat,它继承了Animal类,那么后者就是前者是父类.我可以通过   Cat c = new Cat(); 实例化一个Cat的对象,这个不难理解. 但当我这样定义时:   Animal a = new Cat(); 这代表什么意思呢? 很简单,它表示我定义了一个Animal类型的引用,指向新建的Cat类型的对象.由于Cat是继承自它的父类Animal,所以Animal类型的引用是可以指向C

PHP数字格式化,每三位逗号分隔数字,可以保留小数

在报价的时候为了给浏览者更清晰明确的数字,所以需要用到数字格式化,有两种方法,一种自己写函数,另一种当然是系统自带的,其实我更喜欢系统自带的. 先来系统简单的: string number_format ( float number [, int decimals [, string dec_point, string thousands_sep]] ): 示例代码 echo number_format('169856420'); 输出结果将为: 169,856,420 示例代码 echo nu

java中的数字格式化

/* 关于数字格式化:java.text.DecimalFormat; 数字格式元素: # 任意数字 , 千分位 . 小数点 0 不够补0 */ import java.text.DecimalFormat; public class NumberTest01{ public static void main(String[] args){ //1.创建数字格式化对象 //需求:加入千分位. DecimalFormat df = new DecimalFormat("###,###")

搜集的 C#:String.Format数字格式化输出

今天需要用到 大额的金额数字转换 ,上网搜了一下有人整理好了 于是转载过来 ,备用 格式化处理大额度金额: String.Format("{0:N}", "628310.03") 628,310,03 网上收集: int a = 12345678; C#数字格式化之格式为sring输出 Label1.Text = string.Format("asdfadsf{0}adsfasdf",a); Label2.Text = "asdfads

5个缺失的 JavaScript 数字格式化函数

/** 下面两个函数都能对浮点数进行四舍五入,保留小数点后两位 **/ function CurrencyFormatted(amount) { var i = parseFloat(amount); if(isNaN(i)) { i = 0.00; } var minus = ''; if(i < 0) { minus = '-'; } i = Math.abs(i); i = parseInt((i + .005) * 100); i = i / 100; s = new String(i)

freemarker数字格式化带来的操作问题

freemarker在解析数据格式的时候,自动默认将数字按3为分割(1,000),这个问题给操作带来一定的额外处理复杂度,解决方法有如下几种: 1.在模板中直接加.toString()转化数字为字符串,如: ${languageList.id.toString()}: 2.在freemarker配置文件freemarker.properties加 <#setting number_format="#">或者 <#setting number_format="

block浅析与使用block导致循环强引用举例

定义语法 外部变量值截获 改变外部变量值 block变量作用域导致block体从栈复制到堆同时变量持有了block体中截获的变量 block变量作用域导致强引用 typedef void(^BlockType)(NSString *str);//声明一个void(^)(NSString *str)的block类型,类型名为BlockType-(void)viewDidLoad{ int i=[self getValuesFrom:^int(int i, int y) {//算法由自己定,值由别人