有条件地替换字符序列

有条件地替换字符序列

我是纯 TeX 领域的菜鸟。此问题中使用的所有命令都是在此网站和“LaTeX Wikibook”的答案的帮助下编写的。我想使用 TeX 命令更改键盘映射。我想对非拉丁文字执行此操作。因此,我已将该文字的所有字符激活,并使用catcodes 和def命令重新定义它们。这里的许多用户都无法阅读该文字,因此我之前的问题没有得到完整的解决方案。在这里,我在这个问题中给出了一个拉丁语示例。

假设我已将 A、B、C、D 分别重新映射到 P、Q、R、S

代码 -

\documentclass{article}
\makeatletter
\catcode`\A=\active
\protected\def A{P}
\catcode`\B=\active
\protected\def B{Q}
\catcode`\C=\active
\protected\def C{R}
\catcode`\D=\active
\protected\def D{S}
\makeatother

\begin{document}
    ABCD
\end{document}

这将产生 -

1

但现在我有一个条件。当 A、B、C 或 D 是不是后面跟着字母“a”,在它们后面添加字母“x”。

因此现在我的代码是-

\documentclass{article}
\makeatletter
\catcode`\A=\active
\protected\def A{\bgroup P\futurelet\tmp\check}
\catcode`\B=\active
\protected\def B{\bgroup Q\futurelet\tmp\check}
\catcode`\C=\active
\protected\def C{\bgroup R\futurelet\tmp\check}
\catcode`\D=\active
\protected\def D{\bgroup S\futurelet\tmp\check}
\protected\def\check{\ifx\tmp a\egroup\expandafter\@gobble\else x\egroup\fi}
\makeatother

\begin{document}
    AaBCD
\end{document}

这将产生 -

2

到目前为止一切都很好。现在我有多个条件。如果 A、B、C 或 D 是不是接着是“a”、“e”、“i”、“o”和“u”,然后添加“x”。

我不知道如何在这一行中添加多个条件 -

\protected\def\check{\ifx\tmp a\egroup\expandafter\@gobble\else x\egroup\fi}

第二个问题 -

我也想针对这种情况调整我的文件。

  1. 如果“A”后面是“X”,则将其更改为“L”
  2. 如果“B”后面是“X”,则将其更改为“M”
  3. 如果“C”后面是“X”,则将其更改为“N”

我甚至不知道如何用 TeX 语言表达这些条件。任何帮助我都感激不尽!

答案1

代码变得有点长。比我最初想象的要长得多。

我认为您的条件不太清楚。我(用蹩脚的伪代码)实现的是:

procedure cur_char // (a, b, c, or d)
  if next_char is lowercase_vowel
    print replacement (cur_char) // replaces ABCD by PQRS
  else
    if next_char is uppercase_X
      override_replacement // changes replacement of ABC to LMN
    end
    print replacement (cur_char) // possibly overriden because of X
    print "x"
  end
end

这或多或少就是代码以过于简单的方式所做的事情。

使用该代码,会发生以下替换:

在此处输入图片描述

我用expl3它来完成这项工作,否则代码会更长。我定义了一个\niranjan_define_active:Nn你应该使用的宏,例如,像这样:

\niranjan_define_active:Nn A { \__niranjan_process:NN A P }

另一对宏\activateall\deactivateall控制何时应发生替换行为。理想情况下,您希望此替换在组中激活以避免混乱。

如果您愿意,可以扩展代码来处理其他类型的替换。这\__niranjan_define_charset_conditional:Nn允许您定义一个条件函数来检查下一个字符是否属于给定的字符集。

但是该代码仅适用于 catcode 为 11 的字符。我没有对其他 catcode 进行任何验证。

我必须说,我怀疑这段代码是否只适用于梵文脚本。但是,由于您需要拉丁字符的示例,因此这里是示例:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
% Main code
\cs_new_protected:Npn \__niranjan_process:NN #1#2
  {
    \cs_set_eq:NN \l__niranjan_curr_char #1
    \cs_set_eq:NN \l__niranjan_replacement_char #2
    \niranjan_deactivate_all:
    \peek_after:Nw \__niranjan_process_aux:
  }
\cs_new_protected:Npn \__niranjan_process_aux:
  {
    \__niranjan_if_lower_vowel:NTF \l_peek_token
      {
        \l__niranjan_replacement_char
        \__niranjan_rescan_token:w
      }
      {
        \__niranjan_if_upper_X:NT \l_peek_token
          { \__niranjan_followed_by_X: }
        \l__niranjan_replacement_char
        x
        \__niranjan_rescan_token:w
      }
  }
\cs_new_protected:Npn \__niranjan_followed_by_X:
  {
    \__niranjan_if_upper_ABC:NT \l__niranjan_curr_char
      {
        \exp_args:Nf \__niranjan_replace_char:n
          { \__niranjan_get_char:N \l__niranjan_curr_char }
      }
  }
\cs_new:Npn \__niranjan_replace_char:n #1
  {
    \exp_last_unbraced:NNf \cs_set_eq:NN \l__niranjan_replacement_char
    \str_case:nnF {#1}
      {
        { A } { L }
        { B } { M }
        { C } { N }
      }
      {#1}
  }
\cs_new_protected:Npn \__niranjan_rescan_token:w
  {
    \peek_N_type:TF
      { \__niranjan_rescan_token:Nw }
      { \niranjan_activate_all: }
  }
\cs_new_protected:Npn \__niranjan_rescan_token:Nw #1
  {
    \niranjan_activate_all:
    \tl_rescan:nn { } {#1}
  }
% Checking for following charset
\cs_set:Npn \__niranjan_tmp:w #1
  {
    \cs_new_protected:Npn \__niranjan_define_charset_conditional:Nn ##1 ##2
      {
        \prg_new_protected_conditional:Npnn ##1 ####1 { T, F, TF }
          {
            \exp_last_unbraced:No \__niranjan_if_charset:wn
              \token_to_meaning:N ####1 #1 \q_nil \q_stop {##2}
          }
      }
    \cs_new_protected:Npn \__niranjan_if_charset:wn ##1 #1 ##2##3 \q_stop ##4
      {
        \quark_if_nil:NTF ##2
          { \prg_return_false: }
          {
            \str_if_in:nnTF {##4} {##2}
              { \prg_return_true: }
              { \prg_return_false: }
          }
      }
    \cs_new:Npn \__niranjan_get_char:N ##1
      { \exp_last_unbraced:No \__niranjan_get_char:w \token_to_meaning:N ##1 }
    \cs_new:Npn \__niranjan_get_char:w #1 ##1 { ##1 }
  }
\use:x { \exp_not:N \__niranjan_tmp:w { \tl_to_str:n { the~letter~ } } }
\__niranjan_define_charset_conditional:Nn \__niranjan_if_lower_vowel:N { aeiou }
\__niranjan_define_charset_conditional:Nn \__niranjan_if_upper_X:N { X }
\__niranjan_define_charset_conditional:Nn \__niranjan_if_upper_ABC:N { ABC }
% Setting active chars
\tl_new:N \g__niranjan_chars_tl
\cs_new_protected:Npn \niranjan_define_active:Nn #1#2
  {
    \cs_gset_protected:cpn { __niranjan_active_letter_#1: } {#2}
    \char_set_active_eq:Nc #1 { __niranjan_active_letter_#1: }
    \tl_gput_right:Nn \g__niranjan_chars_tl { #1 }
  }
\cs_new_protected:Npn \niranjan_activate_all:
  { \tl_map_function:NN \g__niranjan_chars_tl \char_set_catcode_active:N }
\cs_new_protected:Npn \niranjan_deactivate_all:
  { \tl_map_function:NN \g__niranjan_chars_tl \char_set_catcode_letter:N }
\cs_new_eq:NN \activateall \niranjan_activate_all:
\cs_new_eq:NN \deactivateall \niranjan_deactivate_all:
\niranjan_define_active:Nn A { \__niranjan_process:NN A P }
\niranjan_define_active:Nn B { \__niranjan_process:NN B Q }
\niranjan_define_active:Nn C { \__niranjan_process:NN C R }
\niranjan_define_active:Nn D { \__niranjan_process:NN D S }
\ExplSyntaxOff
\begin{document}

\ttfamily

AaBeCiDoAu ->
\activateall
AaBeCiDoAu
\deactivateall

ABCDA ->
\activateall
ABCDA
\deactivateall

AXBXCXDXAX ->
\activateall
AXBXCXDXAX
\deactivateall

\end{document}

答案2

使用,\futurelet您可以得出以下标记是{}或空格标记的情况。

如果以下标记不是这些标记中的任何一个,则可以让 LaTeX 将其作为宏参数处理。

反过来,宏观论点可以用多种方式来检验。

解释你的模糊规范的一种方法是:

\documentclass{article}
\makeatletter
\newcommand\fetchargendgroup[1]{#1\endgroup}%
\begingroup
\def\tmp{\ActiveABCD}%
\catcode`\A=\active
\catcode`\B=\active
\catcode`\C=\active
\catcode`\D=\active
\@firstofone{%
  \expandafter\endgroup
  \expandafter\newcommand\expandafter{\tmp}{%
    \begingroup
    \protected\def A{\bgroup\futurelet\tmp\checka}%
    \protected\def B{\bgroup\futurelet\tmp\checkb}%
    \protected\def C{\bgroup\futurelet\tmp\checkc}%
    \protected\def D{\bgroup\futurelet\tmp\checkd}%
    \catcode`\A=\active
    \catcode`\B=\active
    \catcode`\C=\active
    \catcode`\D=\active
    \fetchargendgroup
  }%
}%
\newcommand\checka{\check{P}{Lx}}
\newcommand\checkb{\check{Q}{Mx}}
\newcommand\checkc{\check{R}{Nx}}
\newcommand\checkd{\check{S}{SxX}}
\protected\def\check#1#2{%
  \ifcat\noexpand\tmp\bgroup\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\egroup#1x}{%
    \ifcat\noexpand\tmp\egroup\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {\egroup#1x}{%
      \ifcat\noexpand\tmp\@sptoken\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
      {\egroup#1x}{%
        \nextargfork{#1}{#2}%
      }%
    }%
  }%
}%
\newcommand*\mya{a}
\newcommand*\mye{e}
\newcommand*\myi{i}
\newcommand*\myo{o}
\newcommand*\myu{u}
\newcommand*\myX{X}
\newcommand\nextargfork[3]{%
  \def\tmp{#3}%
  \ifx\tmp\myX\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
  {\egroup#2}{%
    \ifx\tmp\mya\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
    {\egroup#1}{%
      \ifx\tmp\mye\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
      {\egroup#1}{%
        \ifx\tmp\myi\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
        {\egroup#1}{%
          \ifx\tmp\myo\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
          {\egroup#1}{%
            \ifx\tmp\myu\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
            {\egroup#1}{\egroup#1x#3}%
          }%
        }%
      }%
    }%
  }%
}%
\makeatother

\begin{document}
\verb|\ActiveABCD{AaeBCD AXaBXCXDX}|:  \ActiveABCD{AaeBCD AXaBXCXDX}%
\end{document}

如果这不符合预期,请准确指定有关更换的所有要求。

在此处输入图片描述

相关内容