如何在纯文本中跳过 \jobname 的首字母

如何在纯文本中跳过 \jobname 的首字母

正如标题所述,我想要一个\skipfirstletters纯 TeX 宏,它跳过 \jobname 的第一个字母(catcode 11)。例如,如果 TeX 文件名为测试0xy.tex它应该扩大到0xy

我尝试了以下几行测试0xy.tex

\def\skipfirstletters#1{\ifcat A#1\expandafter\skipfirstletters\else#1\fi}
\skipfirstletters Test0xy\par
\skipfirstletters\jobname\par
\expandafter\skipfirstletters\jobname

\bye

结果就是
0xy 测试0xy 测试0xy

我有很多不明白的地方,例如为什么第 4 行中的扩展\jobname(它之前扩展过吗\skipfirstletters?)不像第 2 行中的普通标记那样表现。

如果这很重要的话,我想使用扩展的宏作为其他宏的参数。

非常感谢社区并且抱歉我对 TeX 的了解不够。

答案1

中的标记\jobname类似于\string并且具有 catcode 12(如果是空格则为 10),但是您仍然可以测试插槽的 catcode 设置以测试它是否是字母:

\def\skipfirstletters#1{%
\ifnum11=\catcode`#1 \expandafter\skipfirstletters\else#1\fi}
\skipfirstletters Test0xy\par
\expandafter\skipfirstletters\jobname\par
\expandafter\skipfirstletters\jobname

\bye

答案2

一个expl3基于答案的答案,它会自动检查是否\skipfirstletters是一个宏,并且不会吃掉后面的内容,因为要剪切的字符串是作为参数传递的。

\input expl3-generic

\ExplSyntaxOn

\cs_new:Npn \skipfirstletters #1
 {
  \bool_lazy_and:nnTF { \tl_if_single_p:n { #1 } } { \token_if_cs_p:N #1 }
   {
    \egreg_skipfirstletters:o { #1 }
   }
   {
    \egreg_skipfirstletters:n { #1 }
   }
 }

\cs_new:Npn \egreg_skipfirstletters:n #1
 {
  \__egreg_skipfirstletters:N #1 \q_nil
 }
\cs_generate_variant:Nn \egreg_skipfirstletters:n { o }

\cs_new:Npn \__egreg_skipfirstletters:N #1
 {
  \quark_if_nil:NF #1
   {
    \int_compare:nNnTF { \char_value_catcode:n { `#1 } } = { 11 }
     {% check the next one
      \__egreg_skipfirstletters:N
     }
     {% output the character and the rest
      #1 \__egreg_skipfirstletters_end:w
     }
   }
 }

\cs_new:Npn \__egreg_skipfirstletters_end:w #1 \q_nil { #1 }

\ExplSyntaxOff

\edef\fakejobname{\detokenize{Test0xy}}

\skipfirstletters{Test0xy}

\skipfirstletters{\fakejobname}

X\skipfirstletters{abc}X

\edef\test{\skipfirstletters{Test0xy}} {\tt\meaning\test}

\edef\test{\skipfirstletters{\fakejobname}} {\tt\meaning\test}

\bye

这里\fakejobname定义了,所以我不必重命名文件来进行测试:\detokenize我们得到与`\jobname 相同的结果,也就是说,除了保留类别代码 10 的空格之外,所有字符都是类别代码 12。

在此处输入图片描述

相关内容