比较时忽略标点符号

比较时忽略标点符号

我正在尝试比较两个字符串并在比较过程中忽略标点符号。我认为 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.

相关内容