
pdftex tem um comando que é potencialmente útil para pesquisar e dividir strings: \pdfmatch
. No entanto, encontrei poucos exemplos de trabalho na internet. Eu tenho o uso básico planejado. Por exemplo, pegar emprestado um regex dehttps://stackoverflow.com/questions/12643009/regular-expression-for-floating-point-numbers, estas linhas:
\count255=\pdfmatch {[+-]?([0-9]*[.])?[0-9]+} {-4.06}
\message{\number\count255, \pdflastmatch0, \pdflastmatch1}
\end
produza esta saída: 1, 0->-4.06, 1->4
Minha pergunta é: alguém descobriu as regras de expansão \pdfmatch
e se ela pode lidar com classes de personagens como [:alnum:]
?
Eu pergunto sobre classes de caracteres porque a pesquisa do pdftex é supostamente compatível com posix. De acordo com esta página, as classes de personagens estão no padrão posix:https://en.wikibooks.org/wiki/Regular_Expressions/POSIX_Basic_Regular_Expressions. Outras páginas indicam que as classes dependem da localidade. Não consigo fazer com que eles trabalhem \pdfmatch
e suspeito que não estou fazendo nada de errado; eles simplesmente não são suportados pelo pdftex.
Algumas outras descobertas que fiz estão relacionadas à parte de expansão da minha pergunta: ^
e $
funcionam como âncoras sem nenhuma alteração em seus códigos de gato. Eu também descobri que isso \pdfmatch
faz pelo menos alguma expansão. Você não pode usar \$
como âncora quando se trata do TeX simples \chardef
. Mas se for alterado para \def\${$}
(sem fantasia literalmente), então $
se \$
comporte de maneira semelhante.
O que foi dito acima nos faz pensar se a expansão é completa como an \edef
ou apenas um nível como an \ifx
, e quais dos caracteres especiais do TeX devem ser escapados ou passados como catcode12. Os aparelhos, mesmo quando equilibrados, são especialmente intrigantes. Exemplos práticos \strmatch
ou regras seriam muito apreciados.
PS: Estou ciente das soluções regex com luatex. É especificamente sobre o pdftex que estou pensando. Obrigado!
Responder1
O código-fonte regex nas fontes pdftex tem algum suporte opcional para classes de caracteres, mas não tem suporte de localidade, portanto não é utilizável de forma confiável com caracteres não ASCII, qualquer entrada UTF-8 será vista como múltiplos bytes e não como caracteres 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
produz
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->
onde o teste 2 mostra [:digit:]
não é uma classe de caracteres, mas simplesmente aquele conjunto de caracteres: d i g t
o teste 3 mostra [[:digit:]]
é a classe de personagem (obrigado @egreg)
O teste 4 mostra que tanto a string quanto a regex são totalmente expandidas antes do início do processamento da regex.
Os testes 5 a 8 com o token chardef não expansível \DOLLAR
mostram que se a expansão não consistir puramente em tokens de caracteres, nada corresponde.
Responder2
A sintaxe para \pdfmatch
é indicada na página 45 do manual (rev. 905)
\pdfmatch
[ icase ] [ subcount
⟨inteiro⟩ ]
⟨texto geral⟩ ⟨texto geral⟩ (expansível)
Como ambos os argumentos são ⟨texto geral⟩, seu conteúdo está sujeito a expansão total como acontece com \message
.
Assim, se você precisar escapar de um caractere para fazer uma regex, digamos, \+
para corresponder a um literal +
, você precisa \noexpand\+
de ou [+]
(veja o exemplo abaixo).
Classes de caracteres [:alpha:]
e [:digit:]
são [:alnum:]
suportadas (com colchetes duplos, é claro).
Para corresponder ao final da string você apenas usa $
, e o início da string é ^
.
Qual conjunto de caracteres? Lembre-se de que pdftex
é de 8 bits, portanto o suporte a UTF-8 está fora de questão (mas em alguns casos pode funcionar com 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
O console irá imprimir
1: 1; 0->1x
2: 1; 1->2y
3: 1; 0->a2c+
4: 1; 4->d3f+
5: 1; 0->a2c+
6: 1; 1->à
Se você usar
\pdfmatch{\unexpanded{<regex>}}{<text>}
o ⟨regex⟩ pode estar na sintaxe POSIX padrão. Por exemplo, o exemplo 3 acima pode ser
\count255=\pdfmatch{\unexpanded{[[:alnum:]]*\+}}{a2c+d3f+}