如何使用 \lccode 操作字母和数字?

如何使用 \lccode 操作字母和数字?

如果\lccode不改变类别代码,那么不应该根据小写字母技巧也适用于数字吗?那么,适用于任何字符吗?

\documentclass{article}
\usepackage{fontspec}% xelatex

\long\def\clownaround#1{% based on https://tex.stackexchange.com/a/219497/13552
  \begingroup% only needed to limit scope of formatting macros
  \ttfamily%
  \begingroup\lccode`~=`0\lowercase{\endgroup\def~}{YOUVEBEENPSYCHED0}%
  \begingroup\lccode126=48\lowercase{\endgroup\def~}{YOUVEBEENPSYCHED0} % equivalent of prev line
  \begingroup\lccode`~=`/\lowercase{\endgroup\def~}{YOUVEBEENFOOLED/}%
  \begingroup\lccode`~=`a\lowercase{\endgroup\def~}{YOUVEBEENDUPEDa}%
  \catcode`/=\active\catcode`.=\active% what does this do?
  \scantokens{#1\noexpand}%
  \endgroup%
}
\begin{document}

\clownaround{01/a}% Expected output: YOUVEBEENPSYCHED01YOUVEBEENFOOLED/YOUVEBEENDUPEDa

\end{document}

答案1

为了回答提出的问题,“基于\lowercase技巧的代码”适用于数字或任何字符。问题中有几个不同之处;分别介绍它们可能有助于澄清问题:


  1. 您可以为任何字符给出定义,但仅当 TeX 遇到该字符是活动字符时才使用该定义。

为字符赋予定义只是将该定义存储在某个表中。当 TeX 遇到字符时,如果它的类别代码为 11(“字母”)或 12(“其他字符”),TeX 只会排版该字符,如果它的类别代码为 3(“数学移位”,如$),TeX 会进入或退出数学模式,等等。只有当字符的类别代码为 13(“活动字符”)时,TeX 才会查找该字符的定义并使用它。

这是问题中提出的主要内容,这里有一个更简单的例子:

\documentclass{article}
\begin{document}

\catcode`Z=13  % Makes Z an active character
\defZ{Duck}    % Gives Z the definition "Duck"
\catcode`Z=11  % Makes Z a letter again

Z Z Goose      % Output: Z Z Goose

\catcode`Z=13  % Makes Z an active character
Z Z Goose      % Output: Duck Duck Goose
\end{document}

  1. 在这个例子中,技巧\lowercase只是一种避免设置 catcode 并返回的方法。(因为~inside\lowercase导致 token 的 catcode 为~,但实际字符为 的小写版本~。)

例如,下面已经说明了问题的许多特征,而没有群体和的复杂化\scantokens

\documentclass{article}

\begin{document}

\ttfamily
\lccode`~=`0 \lowercase{\def~}{YOUVEBEENPSYCHED0} % Gives the character 0 the definition "YOUVEBEENPSYCHED0"
\lccode`~=`/ \lowercase{\def~}{YOUVEBEENFOOLED/}  % Gives the character / the definition "YOUVEBEENFOOLED/"
\lccode`~=`a \lowercase{\def~}{YOUVEBEENDUPEDa}   % Gives the character a the definition "YOUVEBEENDUPEDa"
\catcode`/=\active % Makes the character / active (so that / will be replaced by its definition)
\catcode`0=\active % Makes the character 0 active (so that 0 will be replaced by its definition)

01/a               % Output: YOUVEBEENPSYCHED01YOUVEBEENFOOLED/a

\end{document}

output without a active

请注意,这里我们给了角色a一个定义,但它从未使用过(因为角色的 catcode 不为\active= 13)。


  1. \catcode如果我们想将设置或的效果限制\lccode在某个区域,那时我们就需要\begingroup和的进一步复杂化\endgroup(如问题中所示)。

当字符a处于活动状态时,\relax将被解释为\rel后跟a后跟x,因此 TeX 会抱怨未定义的控制序列\rel。 (\scantokens有趣的是,这不会导致错误,而只是做了错误的事情。)所以我们需要小心并将其括在一个组中:在前面刚刚提到的文档中,在之前添加以下内容\end{document}

% We need to be more careful with the character 'a', because
% otherwise \relax will be interpreted as \rel, then a, then x.
\def\clownaround{
  \begingroup
  \catcode`a=\active
  \scantokens{01/a}
  \endgroup
}
\clownaround

output with a active

0这里使用了、/和的定义a\begingroup\endgroup限制了 的范围,\catcode`a = 13以便 等\relax以后仍能起作用。 和\scantokens的使用使得“01/a”使用该点(当宏\clownaround展开并遇到时)的 catcode 进行扫描,而不是使用定义\scantokens宏时的 catcode 。\clownaround

问题中的另一个技巧\begingroup\endgroup

\begingroup\lccode`~=`0\lowercase{\endgroup\def~}{YOUVEBEENPSYCHED0}

这尽可能地限制了的范围\lccode,以防我们稍后要求的小写版本,~0实际上我们得到的是其他版本。


  1. 这里不需要末尾\noexpand\scantokens;它只是\scantokens为了避免出现空格而使用的一般做法。

你的问题中的例子来自这里从哪里得到的这里,但看到这里这里有关\noexpand末尾 的内容\scantokens

答案2

当你重新扫描材料时,e-TeX 会应用目前活跃类别代码。在本例中,除受以下行影响的两个类别代码外,均适用“正常”类别代码

\catcode`/=\active\catcode`.=\active

因此重新扫描后0ETC。作为“其他”角色,而\lowercase“技巧”已经定义了一个积极的 0扩展为某物没有区别。你需要让你感兴趣的每个角色都“活跃”:

\catcode`0=\active
\catcode`a=\active
% Others

这引出了一个简单的例子

\documentclass{article}

\long\def\clownaround#1{% based on https://tex.stackexchange.com/a/219497/13552
  \begingroup% only needed to limit scope of formatting macros
  \ttfamily%
  \begingroup\lccode`~=`0\lowercase{\endgroup\def~}{YOUVEBEENPSYCHED0}%
  \begingroup\lccode`~=`/\lowercase{\endgroup\def~}{YOUVEBEENFOOLED/}%
  \begingroup\lccode`~=`a\lowercase{\endgroup\def~}{YOUVEBEENDUPEDa}%
  \catcode`/=\active
  \catcode`\0=\active
  \catcode`\a=\active
  \endlinechar=-1 %
  \scantokens{#1}%
  \endgroup%
}
\begin{document}

\clownaround{01/a}% Expected output: YOUVEBEENPSYCHED1YOUVEBEENFOOLEDYOUVEBEENDUPED

\end{document}

相关内容