4

这是一次令人着迷的调试体验。你能看出以下两行之间的区别吗?

StringReplace["–", RegularExpression@"[\\s\\S]" -> "abc"]
StringReplace["-", RegularExpression@"[\\s\\S]" -> "abc"]

当您评估它们时,它们会做非常不同的事情。事实证明,这是因为第一行中被替换的字符串由一个 unicode 破折号组成,而不是第二行中的普通旧 ascii 破折号。

对于 unicode 字符串,正则表达式不匹配。我的意思是正则表达式“[\s\S]”的意思是“匹配任何字符(包括换行符)”,但 Mathematica 显然将其视为“匹配任何ascii字符”。

如何修复正则表达式,以便上面第一行的计算结果与第二行相同?或者,是否有一个 asciify 过滤器可以先应用于字符串?

PS:Mathematica 文档说它的字符串模式匹配是建立在 Perl 兼容的正则表达式库(http://pcre.org)之上的,所以我遇到的问题可能不是 Mathematica 特有的。

4

3 回答 3

3

这是我最初用作解决方法的 asciify 函数:

f[s_String] := s
f[x_] := FromCharacterCode[x]

asciify[s_String] := 
  StringJoin[f /@ (ToCharacterCode[s] /. x_?(#>255&) :> "&"<>ToString[x]<>";")]

然后,感谢@Isaac 的回答,我意识到“。” 因为正则表达式似乎没有这个 unicode 问题。我从Mathematica 中的 Bug 的答案中了解到:正则表达式应用于非常长的字符串,“(。| \ n)”是不明智的,但“(?s)”。被推荐。所以我认为最好的解决方法如下:

StringReplace["–", RegularExpression@"(?s)." -> "abc"]
于 2010-03-25T02:41:53.790 回答
3

我会用 aStringExpression代替RegularExpression. 这可以按需要工作:

f[s_String] := StringReplace[s, _ -> "abc"]

在 aStringExpression中,Blank[]将匹配任何内容,包括非 ASCII 字符。

编辑以响应版本更新:从Mathematica 11.0.1 开始,它看起来像字符代码高达2^16 - 1(称为最大值FromCharacterCode)的字母字符,现在的结果StringMatchQ[LetterCharacter]LetterQ.

AllTrue[FromCharacterCode /@ Range[2^16 - 1], 
 LetterQ@# === StringMatchQ[#, LetterCharacter] &]
(* True *)
于 2010-03-26T15:10:08.357 回答
1

用于正则表达式"(.|\n)"的输入似乎对我有用。模式匹配.(任何非换行符)或\n(换行符)。

于 2010-03-25T03:51:26.040 回答