Gehen Sie einfach zum Beispiel: Fügen Sie zwischen jeweils drei Zahlen Kommas ein
"123456789".replace(/(\d{3})(?:[^$])/g, ",");
//"123,567,9"
"123456789".replace(/(\d{3})(?=[^$])/g, ",");
//"123,456,789"
Ein weiteres Beispiel, das im vorherigen Forum erschien, ist das Einfügen von Kommas zwischen jeweils drei Zahlen
先看看 (?=pattern) 的使用,下面这个是正确的:
function groupByCommas(n) {
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
console.log(groupByCommas(1234567)); //1,234,567
如果我们把 ?= 换成 ?: 的话:
function groupByCommas(n) {
return n.toString().replace(/\B(?:(\d{3})+(?!\d))/g, ",");
}
console.log(groupByCommas(1234567)); //1,
Unnötig zu erwähnen, dass es sich bei den beiden Konzepten um eine Antwort handelt, die lautet: Der Unterschied besteht darin, dass ?= eine positive positive Aussage ist und die Übereinstimmung nicht die Abfragelänge einnimmt, während ?: eine Nicht-Erwerbs-Übereinstimmung ist Der Abgleich belegt die Abfragelänge.
Aber ich verstehe die Aussage, dass die Abfrage die Länge hier einnimmt, nicht ganz. Bedeutet das, dass das erste Beispiel (?=[^$]) nicht endend ist, also die Mindestlänge von Das Nicht-Ende nach 123 besteht aus 1 Zeichen, also wurden 4 durcheinander ersetzt? Warum ersetzen Sie es dann nicht einfach bis zum Ende? Das zweite Beispiel (?=(d{3})+(?!d)) entspricht 3 oder einem Vielfachen von 3 und stimmt direkt mit dem Ende überein, sodass 234567 auch direkt ersetzt wird? Mein Verständnis ist also definitiv falsch
Ich verstehe es nicht ganz. Ich begrüße Sie, meine Verwirrung mit Beispielen zu beantworten.
"123456789".replace(/(\d{3})(?:[^$])/g, "$1,");
()
表示捕获型括号,(?:)
表示非捕获型括号,所以第一个括号匹配的内容会放在$1中,第二个括号匹配的内容不会放在$2
中。\d{3}
表示连续三个数字,[^$]
表示匹配一个字符,只要这个字符不是$符号,需要注意的是[]
表示匹配里面的任意一个字符,但是肯定是要有一个的,所以[]
匹配出来的字符的长度肯定是1,不存在0的情况,另外在[$]
里面的$符号是没有特殊含义的,就是$这个字符,而不是匹配字符串的结尾。因为
\d{3}
匹配三个字符,[^$]
匹配一个字符,所以这个正则匹配4个字符;来看匹配过程,首先"1234"是满足的,"123"匹配\d{3}
,"4"匹配[^$]
,此时$1="123"
,所以"1234"被替换成"123,"。然后从5开始下次匹配,类似的"5678"满足条件,$1="567"
,所以"5678"被替换成"567,"。然后从9开始匹配,下面没有匹配了,匹配结束,结果为"123,567,9"。"1234567".replace(/\B(?:(\d{3})+(?!\d))/g, ",");
\B
匹配非单词边界,也是一个位置,没有宽度,(\d{3})+
匹配3的倍数数字序列,且个数至少是3个,+
是量词,表示1到多次,默认是贪婪的,贪婪就是尽可能多的匹配,(?!d)表示这个位置后面不是数字。看例子,首先
\B
不匹配行首,所以匹配的位置移动到"1"后面的位置,此时\B
匹配1后面的位置,然后"234", "567"匹配d{3},因为是贪婪匹配,所以(d{3})+匹配"234567",然后因为7后面是字符串的结尾了,所以满足断言(?!\d)
不是数字,所以整个正则的匹配结果是"234567",所以"234567"被替换成了","
。1不动,所以"1234567"变成了"1,"。"123456789".replace(/(\d{3})(?=[^$])/g, "$1,");
这个正则表达式不满足"千分位添加逗号"的需求,"123456789"只是个特例(位数正好是3的倍数),换成"12345678"结果是"123,456,78"。
占据或"消耗"的意思是说匹配的部分是否可被其他正则 (后面的断言,或
/ /g
的下一次) 再匹配。如果"消耗"掉了就不能再匹配了。另外例1
[^$]
是匹配一个非$
的字符,和行末无关。(?=456)
匹配一个位置,这个位置后面跟了456
。比如
123(?=456)
会匹配123456
中的123
,而不会匹配123457
中的123
,不占用的意思是,至匹配123
后面的456
并不会被占用掉。123456
匹配的是123456
, 而123(?=456)456
同样匹配123456
后面加了(?=456)
其实是没有什么意义的。正则中可以用括号改变优先级等,另外,对于加括号的部分,会从左到右分配递增的分配一个编号,在后面可以用编号引用这一部分匹配到的文本。在JS
replace
里,替换的部分可以用$1
之类的引用这一部分的匹配。比如
(a)\1
会匹配两个连续的a,([A-Z])\1
匹配两个连续相同的大小字母,(A-Z)\1([a-z])\2
匹配两个连续的大小字母,后面跟两个连续的小写字母(大小写字母可以不同)。有时候,我们只想改变优先级,不想分配编号(很少用到),就用
(?:)
比如
(a)(?:b)(c)\1\2
匹配abcac
,但是(a)(b)(c)\1\2
匹配abcab
.http://zonxin.github.io/post/...
用
()
括住的是可以使用$1(到$9)
去匹配的如下面这个,可以使用$1去匹配(捕获)到括号里的匹配到的值
,
。使用
(?:)
则是不捕获这一个。就是不能通过$1
,去取得括号取得的值上面两个都是匹配出含
,
的值来看下面这个,
(?=)
是用于匹配,但是不出现在结果里的。下面这个的结果就没有,
三个代码的结果如图
这个写法是很有用的,有一些内容不希望出现在结果里,但是不用它又匹配不全,就可以用这个了
这2个功能毫不相干
模式1
pattern1(?=pattern2)
正向肯定断言;模式2(?:pattern3)
非捕获性分组1.
模式1
: pattern2 本身不参与匹配,对pattern1的匹配结果(ret1)进行断言:字符串中 ret1之后的内容是否匹配pattern2?若是,则ret1为模式1
匹配结果,若否,则ret1不是模式1
匹配结果。当然,不匹配pattern1,则也不匹配模式1
。举例:
2.
模式2
主要用于区别捕获性分组(pattern4)
,记为模式3
在数学中小括号用于进行一次优先运算;而
模式3
,除了对代码进行隔离,pattern4参与了匹配,且对pattern4的匹配结果进行了存储
对于
模式2
(?:pattern3)的非捕获性分组,则表示不会对pattern3的结果进行存储,但本身pattern3参与了匹配,主要用于对代码进行隔离。也就是要表现
()
本来的意义,而()
在正则表达式中有了捕获性分组的定义,于是增加一个
?:
以示区别。这和转义符\
有异曲同工的妙处。举例
@luckness 对题主的内容进行了详细解答,而我对题主标题进行了解答。