我正在尝试比较两个字符串并在比较过程中忽略标点符号。我认为 catcode 重新定义将是一种很好的方法。但显然,的使用\catcode
有很多细微差别。
我通过比较两个字符串(一个是“x”,另一个是“x,”)来制作下面的 MWE。在 MWE 中,您将看到三个不同的地方,我可以在其中调用 catcode 来忽略逗号(catcode 9)。只有在逗号字符串定义之前的调用才能使比较相等。显然,这不是我想要的。当我将 catcode 更改放入例程中时,逗号仍保留在先前定义的字符串中。
因此,我想,如果我在例程中重新定义带逗号的字符串,在 catcode 更改之后,逗号将从更新的 中删除\edef
。但事实并非如此。如您所见,我尝试了几种不同的方法来重新定义带逗号的字符串,使用了\xdef
、\edef
和的各种组合\expandafter
。
我并不局限于 catcode 方法。如果有办法用命令暂时将逗号重新定义为无\def
,我会非常乐意使用该方法。
关键是这两个字符串在进入检查程序时,其逗号是完整的,而我必须想出一种方法来即时丢弃逗号。
\documentclass{article}
\usepackage{ifthen}
\parindent 0in
\begin{document}
\edef\x{x}
% \catcode`,=9 % ONLY THIS EXTERIOR INVOCATION GIVES EQUALITY
\edef\xcomma{x,}
% \catcode`,=9 % THIS EXTERIOR INVOCATION DOES NOT GIVE EQUALITY
\def\testequalignorecomma#1#2{%
\catcode`,=9 % THIS INTERIOR INVOCATION DOES NOT GIVE EQUALITY
\ifthenelse{\equal{#1}{#2}}{#1~equals #2}{#1~does not equal #2}\\%
\edef\xx{#1}\expandafter\edef\expandafter\xxc\expandafter{#2}%
\ifthenelse{\equal{\xx}{\xxc}}{\xx~equals \xxc}{\xx~does not equal \xxc}\\%
\xdef\xx{#1}\xdef\xxc{#2}%
\ifthenelse{\equal{\xx}{\xxc}}{\xx~equals \xxc}{\xx~does not equal \xxc}%
\catcode`,=12 %
}
\testequalignorecomma{\x}{\xcomma}
\end{document}
答案1
catcode 更改实际上是操纵标记的错误工具,它们仅在将文件中的字符转换为字符标记时使用,并且通常对标记列表没有影响。但是,etex\scantokens
原语确实允许您将标记列表视为文件中的字符列表,因此到目前为止,您可以像这样完成:
\documentclass{article}
\usepackage{ifthen}
\parindent 0in
\begin{document}
\edef\x{x}
% \catcode`,=9 % ONLY THIS EXTERIOR INVOCATION GIVES EQUALITY
\edef\xcomma{x,}
\makeatletter
\def\testequalignorecomma#1#2{%
\catcode`,=9 % THIS INTERIOR INVOCATION DOES NOT GIVE EQUALITY
\edef\tmp{\noexpand\scantokens{\def\noexpand\tmp{\noexpand\ifthenelse{\noexpand\equal{#1}{#2}}}}}%
\tmp\ifhmode\unskip\fi\tmp
{#1~equals #2}{#1~does not equal #2}%
\catcode`,=12 %
}
\makeatother
\testequalignorecomma{\x}{\xcomma}
\end{document}
答案2
无需对类别代码进行改组,以下是使用正则表达式的通用解决方案:
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\compareignorepunct}{mmmm}
{
\segletes_compare_ignorepunct:nnnn {#1}{#2}{#3}{#4}
}
\regex_const:Nn \c_punctuation_regex { [\.\,\:\;\?\!]+ }
\cs_new_protected:Npn \segletes_compare_ignorepunct:nnnn #1 #2 #3 #4
{
\tl_if_single:nTF { #1 }
{ \tl_set:No \l_tmpa_tl { #1 } }
{ \tl_set:Nn \l_tmpa_tl { #1 } }
\tl_if_single:nTF { #2 }
{ \tl_set:No \l_tmpb_tl { #2 } }
{ \tl_set:Nn \l_tmpb_tl { #2 } }
\regex_replace_all:NnN \c_punctuation_regex { } \l_tmpa_tl
\regex_replace_all:NnN \c_punctuation_regex { } \l_tmpb_tl
\tl_if_eq:NNTF \l_tmpa_tl \l_tmpb_tl { #3 } { #4 }
}
\ExplSyntaxOff
\begin{document}
\def\x{x}
\def\xcomma{x,}
\compareignorepunct{\x}{\xcomma}{\typeout{EQUAL}}{\typeout{NOT EQUAL}}
\compareignorepunct{x?}{\xcomma}{\typeout{EQUAL}}{\typeout{NOT EQUAL}}
\end{document}
如果参数是单个标记,我们假设它是要扩展的控制序列。可能会有变化。
终端输出为:
This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012)
restricted \write18 enabled.
entering extended mode
(./ignorepunct.tex
LaTeX2e <2011/06/27>
[...irrelevant lines omitted...]
EQUAL
EQUAL
(./ignorepunct.aux) )
No pages of output.
Transcript written on ignorepunct.log.