
В pdftex есть команда, которая может быть мне полезна для поиска и разделения строк: \pdfmatch
. Однако я нашел несколько рабочих примеров в Интернете. Я понял, как использовать ее в основном. Например, заимствование регулярного выражения изhttps://stackoverflow.com/questions/12643009/regular-expression-for-floating-point-numbers, эти строки:
\count255=\pdfmatch {[+-]?([0-9]*[.])?[0-9]+} {-4.06}
\message{\number\count255, \pdflastmatch0, \pdflastmatch1}
\end
вывести следующий результат: 1, 0->-4.06, 1->4
У меня такой вопрос: кто-нибудь разобрался с правилами расширения \pdfmatch
и может ли оно обрабатывать такие классы персонажей, как [:alnum:]
?
Я спрашиваю о классах символов, потому что поиск pdftex предположительно POSIX-совместим. Согласно этой странице, классы символов находятся в стандарте POSIX:https://en.wikibooks.org/wiki/Регулярные_выражения/POSIX_Basic_Регулярные_выражения. На других страницах указано, что классы зависят от локали. Я вообще не могу заставить их работать \pdfmatch
, и подозреваю, что я не делаю ничего неправильного; они просто не поддерживаются pdftex.
Несколько других открытий, которые я сделал, которые связаны с частью расширения моего вопроса: ^
и $
работают как якоря без каких-либо изменений в их catcodes. Я также обнаружил, что \pdfmatch
делает по крайней мере некоторое расширение. Вы не можете использовать \$
как якорь, когда он исходит из простого TeX \chardef
. Но если изменить на \def\${$}
(без причудливых дословных выражений), то $
и \$
ведут себя аналогично.
Вышеизложенное заставляет нас задуматься, является ли расширение полным, как an, \edef
или только одноуровневым, как an \ifx
, и какие из специальных символов TeX должны быть экранированы или переданы как catcode12. Фигурные скобки, даже сбалансированные, особенно загадочны. Рабочие примеры правил \strmatch
or были бы очень признательны.
PS Я знаю о решениях regex с luatex. Мне интересен именно pdftex. Спасибо!
решение1
Исходный код регулярных выражений в исходниках pdftex имеет некоторую дополнительную поддержку классов символов, но не имеет поддержки локали, поэтому его нельзя надежно использовать с символами, отличными от ASCII; любые входные данные UTF-8 будут рассматриваться как несколько байтов, а не как символы Unicode.
\pdfmatch {[+-]?([0-9]*[.])?[0-9]+} {-4.06}
\immediate\write500{1: \pdflastmatch0, \pdflastmatch1}
% [:digit:] is [:digt] checking for those literal characters
\pdfmatch {[+-]?([:digit:]*[.])?[:digit:]+} {-dddg:ii.ggg}
\immediate\write500{2: \pdflastmatch0, \pdflastmatch1}
% [[:digit:]] is digit class
\pdfmatch {[+-]?([[:digit:]]*[.])?[[:digit:]]+} {-4.06}
\immediate\write500{3: \pdflastmatch0, \pdflastmatch1}
% full expansion happens for both arguments before regex processing
\def\aaa{[0-9]*[.]}
\def\bbb{[+-]?(\aaa)?}
\def\ccc{\bbb[0-9]+}
\def\DDD{4}
\def\EEE{06}
\def\FFF{-\DDD.\EEE}
\pdfmatch {\ccc} {\FFF}
\immediate\write500{4: \pdflastmatch0, \pdflastmatch1}
\chardef\DOLLAR=`$
\pdfmatch {\DOLLAR} {\$}
\immediate\write500{5: \pdflastmatch0}
\pdfmatch {\DOLLAR} {.D.*R}
\immediate\write500{6: \pdflastmatch0}
\pdfmatch {\DOLLAR} {.*}
\immediate\write500{7: \pdflastmatch0}
\pdfmatch {abc\DOLLAR} {a.*}
\immediate\write500{8: \pdflastmatch0}
\end
производит
1: 0->-4.06, 1->4.
2: 0->-dddg:ii.ggg, 1->dddg:ii.
3: 0->-4.06, 1->4.
4: 0->-4.06, 1->4.
5: -1->
6: -1->
7: -1->
8: -1->
где тест 2 показывает, [:digit:]
что это не класс символов, а просто набор символов: d i g t
тест 3 показывает, [[:digit:]]
что это класс персонажа (спасибо @egreg)
Тест 4 показывает, что и строка, и регулярное выражение полностью раскрываются до начала обработки регулярного выражения.
Тесты 5–8 с нерасширяемым токеном chardef \DOLLAR
показывают, что если расширение не состоит исключительно из токенов символов, то ничего не совпадает.
решение2
Синтаксис \pdfmatch
указан на странице 45 руководства (ред. 905).
\pdfmatch
[ icase ] [ subcount
⟨целое число⟩ ]
⟨общий текст⟩ ⟨общий текст⟩ (расширяемый)
Поскольку оба аргумента являются ⟨общим текстом⟩, их содержимое подлежит полному раскрытию, как это происходит для \message
.
Таким образом, если вам нужно экранировать символ для создания регулярного выражения, скажем, \+
для сопоставления с литералом +
, вам нужно \noexpand\+
или [+]
(см. пример ниже).
Поддерживаются классы символов [:alpha:]
, [:digit:]
и (конечно, с двойными скобками).[:alnum:]
Чтобы сопоставить конец строки, вы просто используете $
, а начало строки — ^
.
Какой набор символов? Напомню, что pdftex
он 8-битный, поэтому поддержка UTF-8 исключена (но в некоторых случаях может работать с pdflatex
).
\documentclass{article}
\count255=\pdfmatch{[[:digit:]]x}{1x2y}
\message{^^J1: \the\count255; \pdflastmatch0}
\count255=\pdfmatch{[[:digit:]][[:alpha:]]}{12y}
\message{^^J2: \the\count255; \pdflastmatch0}
\count255=\pdfmatch{[[:alnum:]]*\noexpand\+}{a2c+d3f+}
\message{^^J3: \the\count255; \pdflastmatch0}
\count255=\pdfmatch{[[:alnum:]]*[+]$}{a2c+d3f+}
\message{^^J4: \the\count255; \pdflastmatch0}
\count255=\pdfmatch{^[[:alnum:]]*\noexpand\+}{a2c+d3f+}
\message{^^J5: \the\count255; \pdflastmatch0}
\count255=\pdfmatch{à}{aàa}
\message{^^J6: \the\count255; \pdflastmatch0}
\stop
Консоль выведет
1: 1; 0->1x
2: 1; 1->2y
3: 1; 0->a2c+
4: 1; 4->d3f+
5: 1; 0->a2c+
6: 1; 1->à
Если вы используете
\pdfmatch{\unexpanded{<regex>}}{<text>}
⟨regex⟩ может быть в стандартном синтаксисе POSIX. Например, пример 3 выше может быть
\count255=\pdfmatch{\unexpanded{[[:alnum:]]*\+}}{a2c+d3f+}