РЕДАКТИРОВАТЬ:Решение дляэтотпроблема ниже.
Я пытаюсь выполнить прямую замену целых слов в тексте, но, похоже, использование regex_replace_all
не работает должным образом, поскольку не находит слова, заканчивающиеся на ß.
Я не хочу использовать "s" вместо ßв тексте, который должен быть заменен сам, хотя это работает!
Как MWE:
\documentclass{article}
\usepackage[utf8]{inputenc}
\ExplSyntaxOn
\newcommand{\replaceText}[1]{%
\f_replace_text:n { #1 }
}
\tl_new:N \l_replace_text_tl
\tl_new:N \l_replace_a_tl
\tl_new:N \l_replace_b_tl
\cs_new_protected:Npn \f_replace_text:n #1 {%
\tl_set:Nn \l_replace_text_tl { #1 }
\f_replace:
\tl_use:N \l_replace_text_tl
}
\cs_new_protected:Npn \f_replace: {%
%
\tl_set:Nn \l_replace_a_tl { Grieß }
\tl_set:Nn \l_replace_b_tl { Mehl }
\regex_replace_all:nnN { \b\u{l_replace_a_tl}\b } { \u{l_replace_b_tl} } \l_replace_text_tl
%
\tl_set:Nn \l_replace_a_tl { Grießmenge }
\tl_set:Nn \l_replace_b_tl { Mehlmenge }
\regex_replace_all:nnN { \b\u{l_replace_a_tl}\b } { \u{l_replace_b_tl} } \l_replace_text_tl
%
\tl_set:Nn \l_replace_a_tl { some }
\tl_set:Nn \l_replace_b_tl { more }
\regex_replace_all:nnN { \b\u{l_replace_a_tl}\b } { \u{l_replace_b_tl} } \l_replace_text_tl
%
}
\ExplSyntaxOff
\begin{document}
\noindent Writing some text.
\replaceText{Replacing some text.}
\replaceText{Forgetting to replace Grieß.}
\replaceText{But not forgetting to replace Grießmenge.}
\end{document}
Это производит:
Пишу текст. Заменяю еще текст. Забываю заменитьГрисс. Но не забываем заменить Мельменге.
Однако я ожидал:
Пишу текст. Заменяю еще текст. Забываю заменитьМель. Но не забываем заменить Мельменге.
Почему это происходит и как это предотвратить? Я пробовал несколько способов экранирования символа в регулярном выражении, но мне не удалось заставить это работать.
РЕДАКТИРОВАТЬ: В этом случае, следующие дополнения заставляют это работать: замена всех вхождений ß на его лигатуру "s перед использованием других команд регулярных выражений, которые затем используют только лигатуру "s (внутри поиска, не обязательно в замене), а затем изменение их обратно в конце:
\tl_new:N \l_replace_utf_tl
\tl_new:N \l_replace_ligature_tl
\cs_new_protected:Npn \f_replace_text:n #1 {%
\tl_set:Nn \l_replace_text_tl { #1 }
\tl_set:Nn \l_replace_utf_tl { ß }
\tl_set:Nn \l_replace_ligature_tl { "s }
\regex_replace_all:nnN { \u{l_replace_utf_tl} } { \u{l_replace_ligature_tl} } \l_replace_text_tl
\f_replace:
\regex_replace_all:nnN { \u{l_replace_ligature_tl} } { \u{l_replace_utf_tl} } \l_replace_text_tl
\tl_use:N \l_replace_text_tl
}
решение1
Проблема в том, что для соответствия должна быть граница слова \b
, что означает изменение с \w
-класса на \W
или наоборот.
Но l3regex
в настоящее время не поддерживает полный unicode. Класс \w
содержит только ascii [A-Za-z0-9\_]
. Это означает, что ß
(или, точнее, два байта, составляющие ß) принадлежит \W
, а также точка и поэтому Grieß.
не совпадает.