有多个以下划线和数字开头的命令,且这些命令以相同的文本开头

有多个以下划线和数字开头的命令,且这些命令以相同的文本开头

最近我和一些朋友真正陷入了“让一切都可编译”的泥潭。更具体地说,我们需要做大量的 matlab 计算,然后我们需要将结果放入 tex 文档中。

最近我有点空闲,决定写一个 matlab 脚本来将值及其不确定性界限输出到一个文件中,以正确的格式输出,这样它们就可以在 LaTeX 中调用,并具有正确的有效位数等等,所以不需要动脑子。让我给你举个例子:

1)我有一个 matlab 脚本do.m,它使用数据表单输入文件,对其进行处理并计算我想要的,比如存储在a和 中的值b

2)在脚本的末尾我调用我的savefortex脚本来保存变量ab保存到一个文件中,比如说out.txt,它看起来像这样:

 \def\a{123}
 \def\b{456}

3)我放入\input{out.txt}了我的 LaTeX 文档。

4)我设置了我的 makefile,以便它知道do.m应该调用以获取最新的out.txt

当需要输入大量变量时,这种方法非常方便。不过,最近我遇到了一个问题。我通常将变量及其相应的不确定性边界命名为:as_a、 b 、s_b等。但这与 Tex 不兼容。在家试试这个

\def\s_a{10}
\def\s_b{20}
\s_a and \s_b.

这根本行不通。 同样适用于a1a2等。 但是,例如:

\def\s_a{10}
\s_a

确实有效!似乎 tex 不允许多个带有下划线的宏在下划线前使用相同的文本,即使下划线后的文本不同(同样,这与宏名称中的数字相同)。因此,虽然和可以s_a单独s_b使用,但如果它们都已定义,tex 就不能使用它们中的任何一个!

有什么好的解决方案吗?有没有其他命名方案的建议?或者也许有另一种方法可以从文件中获取数据(这很好,因为当定义了很多宏时,输入会花费很多时间)?

我也希望能够使用siunitx,所以虽然\SI{\a+-\b}{\metre}可以工作,\SI{\a+-\s_a}{\metre}但不能。如果可以的话我会很高兴。

答案1

有两个问题:第一个是

\def\sa{10}
\def\sb{20}

文本\sa and \sb将呈现为

10和20

因为 TeX 忽略控制字后的空格。

第二个问题。控制序列可以由以下任一部分组成:

  1. 仅有的非字母字符(控制符号);或
  2. 由一个或多个字母组成的字符串,即[A-Za-z](控制字)

控制符号后的空格不会被忽略。

然而,定义\def允许使用相当通用的语法:

\def\cs<parameter text>{<replacement text>}

这里<parameter text>可以是任意的标记序列,包括参数指示符#1#9表示参数。但如果存在与参数指示符不同的标记,则它们必须出现在之后\cs。所以

\def\s_a{10}

是合法的,并定义了一个\s命令需要_a后面的两个标记。如果你在这之后说

\def\s_b{20}

该命令\s已重新定义,使用\s_a将触发错误消息

! Use of \s doesn't match its definition.

由于\s后面没有_b

要同时解决这两个问题,请使用

\def\sa/{10}
\def\sb/{20}

然后\sa/ and \sb/渲染为

10 和 20

/因为命令名称后面的必填项会停止忽略空格的功能。

答案2

_您可以通过更改符号的 catcode 来强制 latex 接受。在 (La)Tex 中,每个符号都有其 catcode,因此如果我们将 catcode 更改_为正常,catcode您的命令将起作用。但更改 catcode 可能会导致意外错误。我建议您使用其他命名方案。

\documentclass[12pt]{article}

\catcode`_=11
\def\s_a{10}
\def\s_b{20}

\begin{document}
\s_a and \s_b
\end{document}

您可以使用以下方法解决间距问题xspace

\documentclass[12pt]{article}
\usepackage{xspace}

\catcode`_=11
\def\s_a{10\xspace}
\def\s_b{20\xspace}

\begin{document}
\s_a and \s_b
\end{document}

答案3

我的解决方案:

我已经提出了自己的解决方案,虽然它符合“从文件获取数据的另一种方法“。

我使用这个函数来设置一个值:

\DeclareDocumentCommand{\Mset}{m m g}
{
    \IfNoValueTF{#3}{
        \pgfkeyssetvalue{/matlab/#1/val}{#2}
        \pgfkeyssetvalue{/matlab/#1/e}{}
    }{
        \pgfkeyssetvalue{/matlab/#1/val}{#2}
        \pgfkeyssetvalue{/matlab/#1/e}{e#3}
    }

}
% eg:
\Mset{a}{124}         % set value of 'a' to 124
\Mset{b}{124}{2}      % set value of 'a' to 124e2

我可以使用以下方法获取它的文字值:

\newcommand{\M}[1]
{
    \pgfkeysvalueof{/matlab/#1/val}\pgfkeysvalueof{/matlab/#1/e}
}
% eg:
\M{a}     % results in: 124
\M{b}     % results in: 124e2

或者它的值不带指数:

\newcommand{\Mval}[1]
{
    \pgfkeysvalueof{/matlab/#1/val}
}
% eg:
\Mval{a}     % results in: 124
\Mval{b}     % results in: 124

然后我定义了自己的SI命令:\MSI

\DeclareDocumentCommand{\Mparse}{m g m}{

    \IfNoValueTF{#2}{
        \SI{ \M{#1}}{#3}
    }{
        \SI{ \Mval{#1}+-\M{#2} }{#3}
    }
}

\DeclareDocumentCommand \MSI { >{ \SplitArgument{1}{+} } m m}
{
    \Mparse #1 {#2}
}

%eg:
\MSI{a}{m}     % same as: \SI{124}{m}
\MSI{b}{m}     % same as: \SI{124e2}{m}

这是一个很酷的功能:

\Mset{c}{100}{2}
\Mset{s_c}{12}{2}
\MSI{c+s_c}{m}       % same as: \SI{100+-12e2}{m}

我实际上可以调用\MSI值的名称。这只有在和的指数值相同时才能正常工作cs_c因为它只取的指数值s_c。因为我的 matlab 函数输出的值与c和的指数对应s_c,这对我来说并不重要。但我可能很快就会实现某种警告。

这需要xparse包,以及pgfplots包。

\Mparse用这个定义替换一些最小的错误跟踪:

\DeclareDocumentCommand{\Mparse}{m g m}{

    \IfNoValueTF{#2}{
        \SI{ \M{#1}}{#3}
    }{
        \comparestrict
        \IfStrEq{\Mexp{#1}}{\Mexp{#2}}{
            \SI{ \Mval{#1}+-\M{#2} }{#3}
        }{
            \text{\tt > > ERROR: not equal exponents in MSI < < }
                    \GenericError{(cont.)\space\space}{The exponents for the inputs here aren't the same, as should be for decent output.}{Check that the exponents are the same.}{Check tex.stackexchange.com question 40070}


        }

    }
}

这利用了以下命令\Mexp

\newcommand{\Mexp}[1]
{
    \pgfkeysvalueof{/matlab/#1/e}
}

它还需要xstring包检查 /matlab/#1/e 中的字符串是否相等。

答案4

我已在以下位置使用标签mymacros.tex

\newlabel{@S_L(d)}{{\unit{-118}{\mega\pascal}}}

然后使用tex文件中的引用:

\ref{@S_L(d)}

相关内容