这是一个迷人的调试体验。 你能发现以下两行之间的区别吗?
StringReplace["–", RegularExpression@"[\\s\\S]" -> "abc"]
StringReplace["-", RegularExpression@"[\\s\\S]" -> "abc"]
在评估它们时,它们会做很多不同的事情。事实证明这是因为在第一行中被替换的字符串包含一个unicode en dash,而不是第二行中的普通旧ascii破折号。
对于unicode字符串,正则表达式不匹配。 我的意思是正则表达式“[\ s \ S]”表示“匹配任何字符(包括换行符)”但Mathematica显然将其视为“匹配任何 ascii 字符”。
如何修复正则表达式,使上面的第一行与第二行的结果相同?或者,是否有一个asciify过滤器,我可以先应用于字符串?
PS:Mathematica文档说它的字符串模式匹配是建立在Perl兼容的正则表达式库(http://pcre.org)之上的,所以我遇到的问题可能不是Mathematica特有的。
答案 0 :(得分:3)
这是一个asciify函数,我最初使用它作为解决方法:
f[s_String] := s
f[x_] := FromCharacterCode[x]
asciify[s_String] :=
StringJoin[f /@ (ToCharacterCode[s] /. x_?(#>255&) :> "&"<>ToString[x]<>";")]
然后我意识到,感谢@ Isaac的回答,“。”作为正则表达式似乎没有这个unicode问题。我从Bug in Mathematica: regular expression applied to very long string的答案中了解到,“(。| \ n)”是不明智的,但是“(?s)”。被推荐。所以我认为最好的解决方法如下:
StringReplace["–", RegularExpression@"(?s)." -> "abc"]
答案 1 :(得分:3)
我会使用StringExpression
代替RegularExpression
。这可以按预期工作:
f[s_String] := StringReplace[s, _ -> "abc"]
在StringExpression
中,Blank[]
将匹配任何内容,包括非ASCII字符。
编辑以响应版本更新:从 Mathematica 11.0.1开始,它看起来像字母代码最多为2^16 - 1
的字母字符(称为作为FromCharacterCode
)的最大值,StringMatchQ[LetterCharacter]
的结果现在与LetterQ
的结果相匹配。
AllTrue[FromCharacterCode /@ Range[2^16 - 1],
LetterQ@# === StringMatchQ[#, LetterCharacter] &]
(* True *)
答案 2 :(得分:1)
使用"(.|\n)"
作为RegularExpression的输入似乎对我有用。该模式匹配.
(任何非换行符)或\n
(换行符)。