让 \csname 忽略下标符号

让 \csname 忽略下标符号

我想知道是否可以\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}

相关内容