正如标题所述,我想要一个\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
我有很多不明白的地方,例如为什么第 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。