javascript - Was ist der Unterschied zwischen ?= und ?: in regulären Ausdrücken?
天蓬老师
天蓬老师 2017-06-15 09:22:42
0
5
1101

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.

天蓬老师
天蓬老师

欢迎选择我的课程,让我们一起见证您的进步~~

Antworte allen(5)
刘奇
  1. "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"。

  2. "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,"。

  3. "123456789".replace(/(\d{3})(?=[^$])/g, "$1,");
    这个正则表达式不满足"千分位添加逗号"的需求,"123456789"只是个特例(位数正好是3的倍数),换成"12345678"结果是"123,456,78"。

typecho

占据或"消耗"的意思是说匹配的部分是否可被其他正则 (后面的断言,或/ /g的下一次) 再匹配。如果"消耗"掉了就不能再匹配了。

"123456789".replace(/(\d{3})(?=[^$])/g, (m, $1) => `{matched=${m} $1=${$1}}`);
// => '{matched=123 $1=123}{matched=456 $1=456}789'
// (?=) 第一次没有消耗掉4, 第二次会从456..开始

"123456789".replace(/(\d{3})(?:[^$])/g, (m, $1) => `{matched=${m} $1=${$1}}`);
// => '{matched=1234 $1=123}{matched=5678 $1=567}9'
// (?:) 第一次消耗掉4,第二次会从567..开始

另外例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去匹配(捕获)到括号里的匹配到的值,

a = '123,456';
a.match(/\d{3}(,)/)

使用(?:)则是不捕获这一个。就是不能通过$1,去取得括号取得的值

a.match(/\d{3}(?:,)/)

上面两个都是匹配出含,的值
来看下面这个,(?=)是用于匹配,但是不出现在结果里的。下面这个的结果就没有,

a.match(/\d{3}(?=,)/)

三个代码的结果如图

这个写法是很有用的,有一些内容不希望出现在结果里,但是不用它又匹配不全,就可以用这个了

世界只因有你

这2个功能毫不相干
模式1pattern1(?=pattern2)正向肯定断言;模式2(?:pattern3)非捕获性分组

1.模式1: pattern2 本身不参与匹配,对pattern1的匹配结果(ret1)进行断言:字符串中 ret1之后的内容是否匹配pattern2?若是,则ret1为模式1匹配结果,若否,则ret1不是模式1匹配结果。当然,不匹配pattern1,则也不匹配模式1

举例:

  var str1='abc',str2='acb';var reg=/a(?=b)/
  console.log(reg.test(str1),reg.test(str2)) //=>true false
  //因为reg.test(str1)为真,输出匹配结果
  console.log(str1.match(reg)[0])  //=>a

2.模式2 主要用于区别捕获性分组(pattern4),记为模式3

在数学中小括号用于进行一次优先运算;而模式3 ,除了对代码进行隔离,pattern4参与了匹
配,且对pattern4的匹配结果进行了存储

对于模式2(?:pattern3)的非捕获性分组,则表示不会对pattern3的结果进行存储,但本身
pattern3参与了匹配,主要用于对代码进行隔离。也就是要表现()本来的意义,而()在正则
表达式中有了捕获性分组的定义,于是增加一个?:以示区别。这和转义符\有异曲同工的妙处。

举例

var  str='abc'
var  reg1=/(\w)(\w)(\w)/
var  reg2=/(\w)(?:\w)(\w)/
//捕获了3次,RegExp.$1,RegExp.$2,RegExp.$3...依次存储捕获结果
var ret1=str.match(reg1)
console.log(RegExp.$1,RegExp.$2,RegExp.$3)//=>a b c
var ret2=str.match(reg2)
//捕获了2次
console.log(RegExp.$1,RegExp.$2) //=>a c

@luckness 对题主的内容进行了详细解答,而我对题主标题进行了解答。

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage