Регулярные выражения Mathematica в строках Unicode - PullRequest
4 голосов
/ 25 марта 2010

Это был увлекательный опыт отладки. Можете ли вы определить разницу между следующими двумя строками?

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.

Ответы [ 3 ]

3 голосов
/ 26 марта 2010

Я бы использовал 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 *)
3 голосов
/ 25 марта 2010

Вот функция asciify, которую я сначала использовал в качестве обходного пути:

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

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

Тогда я понял, благодаря ответу @ Исаака, что "." как регулярное выражение, похоже, не имеет этой проблемы Unicode. Из ответов на Ошибка в Mathematica я узнал: регулярное выражение, примененное к очень длинной строке , что "(. | \ N)" опрометчиво, но это "(? S)". Рекомендовано. Поэтому я думаю, что лучшим решением будет следующее:

StringReplace["–", RegularExpression@"(?s)." -> "abc"]
1 голос
/ 25 марта 2010

Использование "(.|\n)" для ввода в RegularExpression, кажется, работает для меня. Шаблон соответствует . (любой не-символ новой строки) или \n (символ новой строки).

...