我很难理解我观察到的多字符unicode符号的一些行为。
以字符串🤚🏾🇺🇸🤚🏾🇺🇸🤚🏾
和正则表达式(🤚🏾|🇺🇸)(?![🏾])
为例,我得到三个匹配:两个标志和最后一手牌。期望:5个匹配,每个符号一次。
因为🤚🏾和🇺🇸都是2个字符符号,我试着写一个非unicode的例子。使用字符串abcdabcdab
和正则表达式(ab|cd)(?![b])
,我得到了预期的5个匹配,每对ab
和cd
各一次。
考虑到🤚🏾
和🏾
之间可能存在一些交互作用,我使用了不同的unicode字符,给我正则表达式(🤚🏾|🇺🇸)(?![🇹])
。这里我得到了与第一个示例相同的结果。
由于🇹
和🏾
通常不单独使用,我尝试使用"normal"unicode或ASCII字符,而不是🇹
。在我的例子中,我使用了🐰
和a
,这给了我5个匹配的预期结果,每个符号一次。
有人能解释这个行为吗,还是这是一个bug?
这种行为只发生在PCRE和JavaScript正则表达式引擎,我用这个网站来测试它。https://regex101.com/
不应该像(?![🏾])
那样在字符类中放入多字节字符。在字符类中,它被分解了。转换成两个字节序列,uD83C
和uDFFE
,匹配它们中的任何一个,而不是作为一个序列。由于手部表情符号是uD83EuDD1AuD83CuDFFE
的一个序列(它以这两个字节结束),因此前瞻被触发并影响了匹配。
要解决这个问题,只需要删除括号并使用(🤚🏾|🇺🇸)(?!🏾)
,这样🏾
字符就可以被视为字节序列,而不是一个或另一个字符。