我想知道是否可以\csname
忽略下标符号。下面是我所指的 MWE:
\documentclass[a4paper,11pt]{book}
% I have several commands with the same prefix
\newcommand{\fooT}{T}
\newcommand{\fooS}{S}
% I want to call these commands from another command with respect to the given parameter
\newcommand{\fooL}[1]{L_{\csname foo#1\endcsname}}
\begin{document}
Without subscript $\fooL{T}$ gives the same thing than $L_{\fooT}$.
With subscript $\fooL{T_j}$ is different from $L_{\fooT_j}$.
\end{document}
据我所知,这种行为是可以预料的,因为\csname
会将所有内容扩展为名为的单个命令\fooT_j
,并将_
其视为名称的一部分,而不是下标字符。是否可以更改此行为,以便返回带有下标的\csname
命令?换句话说,我想给出与相同的东西。\fooT
_j
$\fooL{T_j}$
$L_{\fooT_j}$
我尝试使用\detokenize
和\scantokens
命令:
\newcommand{\fooL}[1]{L_{\expandafter\scantokens{\expandafter\detokenize{\csname foo#1\endcsname}}}}
但我没有得到令人满意的结果。我的想法是分解命令,然后重建它。
我知道我可以改变命令的语法来获得所需的结果,但对我来说保留相同的语法会更方便。
答案1
\documentclass[a4paper,11pt]{book}
% I have several commands with the same prefix
\newcommand{\fooT}{T}
\newcommand{\fooS}{S}
% I want to call these commands from another command with respect to the given parameter
\newcommand{\fooL}[1]{\fooLhelp#1\relax}
\def\fooLhelp#1#2\relax{L_{\csname foo#1\endcsname#2}}
\begin{document}
Without subscript $\fooL{T}$ gives the same thing than $L_{\fooT}$.
With subscript $\fooL{T_j}$ is different from $L_{\fooT_j}$.
\end{document}
曼努埃尔的建议进一步简化了方法:
\newcommand*\fooL[1]{L_{\auxfoo#1}}
\newcommand*\auxfoo[1]{\csname foo#1\endcsname}
因为\auxfoo
只会抓取参数的第一个标记。
附录
\foox
对于底层宏在以下情况下发生的情况,有一些评论讨论:x
宏在不止一个 token 的情况但前提是底层宏观仅有的单独出现或者跟在下标后面。
具体做法如下:
\documentclass[a4paper,11pt]{book}
% I have several commands with the same prefix
\newcommand{\fooT}{T}
\newcommand{\fooTTT}{TTT}
\newcommand{\fooS}{S}
% I want to call these commands from another command with respect to the given parameter
\newcommand{\fooL}[1]{\fooLhelp#1_\relax}
\def\fooLhelp#1_#2\relax{L_{\csname foo#1\endcsname\ifx\relax#2\relax\else_\foolHelp#2\fi}}
\def\foolHelp#1_{#1}
\begin{document}
Without subscript $\fooL{T}$ gives the same thing than $L_{\fooT}$.
With subscript $\fooL{T_j}$ is different from $L_{\fooT_j}$.
With longer base $\fooL{TTT}$ and subscript $\fooL{TTT_j}$.
\end{document}
答案2
使用时\csname
总是有可能得到意外结果,所以我还添加了错误检查。
\documentclass{article}
\newcommand{\fooT}{\mathcal{T}}
\newcommand{\fooS}{\mathbf{S}}
\newcommand{\fooST}{\mathrm{ST}}
\makeatletter
\newcommand{\fooL}[1]{\fooL@aux#1_\fooL@aux}
\def\fooL@aux#1_#2\fooL@aux{%
\ifcsname foo#1\endcsname
\csname foo#1\endcsname
\else
\@latex@error{Wrong argument}{The 'foo#1' command does not exist}%
\fi
\if\relax\detokenize{#2}\relax
% no _ in the argument
\else
\fooL@aux@i#2% remove the surplus _
\fi
}
\def\fooL@aux@i#1_{_{#1}}
\makeatother
\begin{document}
$\fooL{T}$ and $\fooL{T_j}$
$\fooL{S}$ and $\fooL{S_jkl}$
$\fooL{ST}$ and $\fooL{ST_j}$
$\fooL{X}$
\end{document}
这给出
并且控制台上还显示以下消息:
! LaTeX Error: Wrong argument.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.31 $\fooL{X}
$
? h
The 'fooX' command does not exist
?
一种expl3
实现方式:
\documentclass{article}
\usepackage{xparse}
\newcommand{\fooT}{\mathcal{T}}
\newcommand{\fooS}{\mathbf{S}}
\newcommand{\fooST}{\mathrm{ST}}
% look for _ in the argument
\NewDocumentCommand{\fooL}{>{\SplitArgument{1}{_}}m}{\fooLaux#1}
\ExplSyntaxOn
\NewDocumentCommand{\fooLaux}{mm}
{
\cs_if_exist:cTF { foo#1 }
{
\use:c { foo#1 }
}
{
\msg_error:nnn { mp } { foo-not-exist } { #1 }
}
% if _ is found, argument #2 has value
\IfValueT{#2}{\sb{#2}}
}
% define the error message
\msg_new:nnnn { mp } { foo-not-exist }
{
Wrong~argument
}
{
The~command~'foo#1'~does~not~exist
}
\ExplSyntaxOff
\begin{document}
$\fooL{T}$ and $\fooL{T_j}$
$\fooL{S}$ and $\fooL{S_jkl}$
$\fooL{ST}$ and $\fooL{ST_j}$
$\fooL{X}$
\end{document}