防止数学模式将宏输入解析为数学?

防止数学模式将宏输入解析为数学?

基本问题

我正在尝试生成一个命令\m序列

  1. 从数学模式中调用,带有一个参数list
  2. 用和(分别)“替换” 中的所有和,;list&\\
  3. 创建一个pmatrix以 1 & 2 为内容的输出

例如,代码

\[
    \m{a,b;c,d}\m{x;y}
\]

应扩展为相当于以下内容:

\[
    \begin{pmatrix}a&b \\ c&d\end{pmatrix}\begin{pmatrix}x \\ y\end{pmatrix}
\]

在花了比我应该花的更多的时间之后,我想出了以下解决问题的部分方法xstring

\def\foo#1{
    \StrSubstitute{#1}{,}{&}[\result]

    \verbtocs{\bslashes}|\\|
    \expandarg
    \StrSubstitute{\result}{;}{ \bslashes }[\result]
}

\begin{document}
    % Fairly complicated matrix input
    \foo{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}
    \[
        \begin{pmatrix}
            \result
        \end{pmatrix}
    \]
\end{document}

这接近我所期望的,但我还没有想出一种方法来用作\foo辅助函数来\m获得我想要的。我\m在想在序言中定义

\def\m#1{
    \foo{#1}
    \begin{pmatrix}
        \result
    \end{pmatrix}
}

可以工作,但即使在数学模式下调用一些简单的东西\m{a}也会产生错误。看起来数学模式试图解析定义\m而不是完全\m展开,但我对此工作原理的理解太有限,不知道如何修复我的代码。

有没有办法修改 的定义\m\foo使其按我的要求执行?我能否以某种方式退出 定义中的数学模式\m以避免这些错误?

答案1

这是一种老式的方法,使用带有分隔参数的宏。

\documentclass{article}
\usepackage{amsmath} % for pmatrix environment

\newtoks\asqltoks
\makeatletter

\def\gobtilundef #1\undef {}

\def\matlabmatrix #1{\asqltoks{\begin{pmatrix}}\@asqlA #1;\undef;}

% \def\@asqlA #1;{\gobtilundef #1\@asqlE\undef\@asqlR #1,\undef,}
% update: simplified to ->
\def\@asqlA #1;{\@asqlR #1,\undef,}

\def\@asqlB #1;{\gobtilundef #1\@asqlE\undef
                \asqltoks\expandafter{\the\asqltoks \\}\@asqlR #1,\undef,}

\def\@asqlE\undef #1\undef,\undef,{%
    \asqltoks\expandafter{\the\asqltoks\end{pmatrix}}\the\asqltoks }

\def\@asqlR #1,{\asqltoks\expandafter{\the\asqltoks #1}\@asqlS }
\def\@asqlS #1,{\gobtilundef #1\@asqlZ\undef
                \asqltoks\expandafter{\the\asqltoks &#1}\@asqlS }
\def\@asqlZ #1\@asqlS {\@asqlB }

\makeatother

\begin{document}

$\matlabmatrix {m}$

$\matlabmatrix {m,n}$

$\matlabmatrix {m,n;p,q}$

$\matlabmatrix {a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}$

\end{document}

矩阵

答案2

以下是具有功能的实现expl3

\documentclass{article}
\usepackage{xparse,amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\matlabmatrix}{m}
 {
  \asql_matlab_matrix:n { #1 }
 }

\seq_new:N \l_asql_rows_seq
\seq_new:N \l_asql_one_row_seq
\tl_new:N \l_asql_matrix_tl

\cs_new_protected:Npn \asql_matlab_matrix:n #1
 {
  % clear the token list variable containing the final data
  \tl_clear:N \l_asql_matrix_tl
  % split the argument at the semicolon
  \seq_set_split:Nnn \l_asql_rows_seq { ; } { #1 }
  % build one row at a time
  \seq_map_inline:Nn \l_asql_rows_seq
   {
    \__asql_build_row:n { ##1 }
   }
  % print the matrix
  \begin{pmatrix}
  \tl_use:N \l_asql_matrix_tl
  \end{pmatrix}
 }

% the inner function
\cs_new_protected:Npn \__asql_build_row:n #1
 {
  % split the input at commas
  \seq_set_split:Nnn \l_asql_one_row_seq { , } { #1 }
  % add the row to the token list variable
  % items are separated by &
  \tl_put_right:Nx \l_asql_matrix_tl
   { \seq_use:Nnnn \l_asql_one_row_seq { & } { & } { & } }
  % add also the \\ row terminator
  \tl_put_right:Nn \l_asql_matrix_tl { \\ }
 }
\ExplSyntaxOff

\begin{document}
\begin{gather*}
\matlabmatrix{a,b;c,d}\matlabmatrix{x;y} \\
\matlabmatrix{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}
\end{gather*}
\end{document}

这很简单:我们首先用分号分割参数;然后用逗号分割每个项目,并逐行构建矩阵的内容。最后将内容插入和之间\begin{pmatrix}进行\end{pmatrix}打印。

在此处输入图片描述

答案3

此代码应该可以完成您想要的操作:

\documentclass{article}
\usepackage{xstring,amsmath}
\newcommand*\mmm[1]{%
    \begingroup\expandarg
    \StrSubstitute{\noexpand#1},&[\result]%
    \StrSubstitute\result{\noexpand;}{\noexpand\\}[\result]%
    \begin{pmatrix}\result\end{pmatrix}\endgroup
}
\begin{document}
\[\mmm{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}\]

\[\mmm{a}\]
\end{document}

答案4

如果你已经在使用xstring,你可以尝试xparse

显然,在最后一行之后pmatrix保留了一个附加行,而无需添加额外的行(与通常的数学环境不同)。但是必须删除附加行,这是通过 完成的。\\&\@gobblesecondoftwo

;我还提供了一个解决方案,它使用 TeX 的分隔参数在s 和s处分割参数,

代码

\documentclass{article}
\usepackage{amsmath}

% xparse solution
\usepackage{xparse}
\makeatletter
\def\@gobblethirdofthree#1#2#3{#1#2}
\def\@gobblesecondoftwo#1#2{#1}
\NewDocumentCommand\foo{>{\SplitList;}m}{
 \begin{pmatrix} \ProcessList{#1}\@foo \end{pmatrix}
}
\NewDocumentCommand\@foo{>{\SplitList,}m}{
  \expandafter\expandafter\expandafter\@gobblesecondoftwo
  \ProcessList{#1}\@@foo \\
}
\def\@@foo#1{&#1}

% plain delimited parameters
\newcommand*{\fooo}[1]{%
  \begin{pmatrix}\foo@split@semi#1;\foo@@@split@semi\foo@@split@semi\end{pmatrix}
}
\def\foo@split@semi#1;#2\foo@@split@semi{%
  \foo@split@comma#1,\foo@@@split@comma\foo@@split@comma
  \ifx\foo@@@split@semi#2\expandafter\@gobble\else
    \expandafter\@firstofone
  \fi{\\\foo@split@semi#2\foo@@split@semi}%
}
\def\foo@split@comma#1,#2\foo@@split@comma{%
  #1
  \ifx\foo@@@split@comma#2\expandafter\@gobble\else
    \expandafter\@firstofone
  \fi{&\foo@split@comma#2\foo@@split@comma}%
}
\makeatother
\begin{document}
$\foo{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}$
$\foo{m}$

$\fooo{a,b,c;d,e_{f,g},h;i,j_{1,e^n},k}$
$\fooo{m}$
\end{document}

输出

在此处输入图片描述

相关内容