用其他字符替换 ASCII 代码定义的字符

用其他字符替换 ASCII 代码定义的字符

我正在尝试替换给定字符串中的某些字符。要替换的字符由其 ASCII 码给出。例如,在 中abc,我想用其他字符(比如说点 ( ))替换字符97(即a,但我还不知道).

现在,a在文档中打印时,\char97\char\thenumber对我来说都一样,但在字符串中替换相应的参数a仅适用于第一个。为什么会这样,我该如何解决?这是我的 MWE(与原始问题没有变化):

\documentclass{book}
\usepackage{xstring}
\newcounter{number}
\setcounter{number}{97}
\newcommand{\replace}[1]{\StrSubstitute{#1}{a}{.}}
\begin{document}
a

\char97

\char\thenumber

\replace{a}

\expandafter\replace{\char97}

\expandafter\expandafter\expandafter\replace{\char\thenumber}

\end{document}

答案1

有一个标准\lowercase技巧,即使用给定的 ASCII 代码创建一个标记。例如,您需要用abcabcacdouble替换字符串中的所有 ASCII 97 个字符?。然后您可以尝试:

\bgroup\lccode`X=97 \lowercase{\egroup \StrSubstitute{abcabcabc}{X}{??}}
output:  ??bc??bc??bc

此代码使用给定的 ASCII 代码(而不是字母)创建标记X,然后\StrSubstitute执行宏。

当然,你处理的字符串不能包含X字母本身。如果这是一个问题,那么你可以创建以下\replace宏:

\def\replace#1{\bgroup \lccode`X=#1 \lowercase{\egroup \replaceA{X}}{abcabcabcXuv}}
\def\replaceA#1#2{\StrSubstitute{#2}{#1}{??}}

\replace{97}
output:  ??bc??bc??bcXuv
\replace{98}
output:  a??ca??ca??cXuv

答案2

TeX\char基元不可扩展。这意味着在示例中尝试扩展

\expandafter\replace\expandafter{\char97}

不执行任何操作,相当于

\replace{\char97}

由于显而易见的原因,它无法匹配文字a。因此,需要一些可扩展的方法将数字转换为字符。经典 TeX 为我们提供了\ifcase原语,它以一般形式使用

\ifcase<number> %
   <case 0>\or
   <case 1>\or
   <case 2>\or
   ...
   <case n>\else
   <no match>
\fi

因此,通过适当的设置,可以进行逐个转换。LaTeX\@alph和 就采用了这种方法\@Alph,它们分别从 1 开始索引小写字母/大写字母:

\@alph{1}% => a

显然,这里需要进行一些数学运算才能正确获得偏移量。这种方法可扩展,但对于长字符列表来说显然很繁琐。

可以设置一个可扩展的“选择性”案例陈述:例如有一个预先内置的expl3

\int_case:nnF { <number> }
  {
    {  97 } { a }
    { 101 } { e }
    { 105 } { i }
    { 111 } { o }
    { 117 } { u }
  }
  { No~match }

对于连续整数范围的短列表,与原语相比,性能会受到影响,但输入格式和清晰度更好,特别是对于长列表。(我认为除了这个之外,还有其他相同概念的实现expl3。)

任何逐案处理方法的问题在于,如果你将目光投向 ASCII 以外的整个 UTF-8 范围。如果使用 LuaTeX,那么一个可扩展的原语,可以完成这项工作

\Uchar97 % => a

如果您能确定正在使用的引擎,这显然是最简单的解决方案。

答案3

我想要实现的是使用\@Alph和实现的\@alph,因为我的输入 ASCII 代码在 az、AZ 范围内。\@Alph等似乎扩展为“真实”字母。正如其他许多人指出的那样,\char是不可扩展的。我希望这有时可以帮助别人。

相关内容