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/Regular_Expressions/POSIX_Basic_Regular_Expressions。其他页面表明这些类与语言环境相关。我根本无法使用它们\pdfmatch
,我怀疑我没有做错什么;它们只是不受 pdftex 支持。
我还发现了一些与我的问题扩展部分相关的其他内容: ^
和可以$
作为锚点工作,而无需更改其 catcode。我还发现\pdfmatch
至少进行了一些扩展。\$
当它来自纯 TeX 时,您不能将其用作锚点\chardef
。但如果更改为\def\${$}
(没有花哨的逐字),则$
和的\$
行为类似。
以上内容让我们怀疑扩展是否像 一样完整\edef
,还是像 一样只有一层\ifx
,以及 TeX 的哪些特殊字符必须转义或作为 catcode12 传入。括号,即使匹配,也特别令人费解。\strmatch
或规则的工作示例将不胜感激。
PS 我知道 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 表明在正则表达式处理开始之前,字符串和正则表达式都已完全扩展。
使用不可扩展的 chardef 标记的测试 5-8\DOLLAR
表明,如果扩展不是纯粹由字符标记组成,则不会有任何匹配项。
答案2
语法\pdfmatch
在手册第 45 页 (rev. 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+}