我尝试做这样的事情(最小的例子):
\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}
\newcommand{\foo}[1]{
\StrSubstitute{#1}{:}{\string&}[\fooo]
\StrSubstitute{\fooo}{-}{\string\\}[\fooo]
\tokenize{\fooo}{\fooo}
\fooo}
\begin{document}
\[\begin{matrix}
\foo{1:2-2:3}
\end{matrix}\]
\end{document}
但是我它不起作用,由于某种原因这是有效的:
\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}
\begin{document}
\StrSubstitute{1:2-2:3}{:}{\string&}[\fooo]
\StrSubstitute{\fooo}{-}{\string\\}[\fooo]
\tokenize{\fooo}{\fooo}
\[\begin{matrix}
\fooo
\end{matrix}\]
\end{document}
对此有什么想法吗?我认为这与 catcodes 有关...
也许有人对这种行为也有解释?
答案1
您的代码无法运行的原因是matrix
环境(或者更确切地说,底层\halign
TeX 基元)&
在 xstring 操作它时(更准确地说,在执行\tokenize
步骤时)可以看到。TeX 认为这是单元格的末尾,插入单元格末尾的材料,包括内部基元\endtemplate
,这会使 xstring 宏阻塞。如果您想看到这种情况,请\tracingall
在之前添加\tokenize
,并得到令人困惑的输出。
那么……我们如何躲避&
TeX 好奇的目光?事实证明,如果 TeX 看到&
(或者更确切地说,带有 catcode 4 的标记,对齐制表符)而它认为该标记在括号内,则该&
标记将保持原样,而不会转换为单元格的末尾。因此,例如,\def\foo{&}
在对齐中出现时不会使 TeX 阻塞:&
隐藏。另一方面,\begin{matrix}abc\string &\end{matrix}
不会显示&
,而是显示$
(单元格末尾材料中的第一个字符)。有关更多信息,请参阅Philippe Goutet 的描述\alignsafe@testopt
。
无论如何,一个解决方案是将所有 xstring 命令放在括号组内,然后\fooo
在其后展开:类似于
\begin{matrix}
{\StrSubstitute{1:2-3:4}{:}{\string&}[\fooo]
\StrSubstitute{\fooo}{-}{\string\\}[\fooo]
\tokenize{\fooo}{\fooo}
\expandafter}\fooo
\end{matrix}
(如果愿意,可以将其包装在命令中)。这样做的缺点是我们基本上是{}1&2\\3&4
在为 TeX 排版,而空括号组在某些情况下可能会影响间距。相反,我会使用“假”括号\iffalse{\fi
和\iffalse}\fi
,这会让 TeX 认为这&
不是单元格的结尾,但不会插入任何要排版的内容。下面\relax
代码中的额外内容是必要的,因为否则 TeX 会在单元格开头完全展开材料,\iffalse{\fi
在尚未记录括号数量时展开得太早。
\documentclass{article}
\usepackage{mathtools}
\usepackage{xstring}
\newcommand{\foo}[1]{%
\relax\iffalse{\fi % <= here
\StrSubstitute{#1}{:}{\string&}[\fooo]%
\StrSubstitute{\fooo}{-}{\string\\}[\fooo]%
\tokenize{\fooo}{\fooo}%
\iffalse}\fi % <= and there
\fooo}
\begin{document}
\[\begin{matrix}
\foo{1:2-2:3}
\end{matrix}\]
\end{document}
\tokenize
其他答案指出,如果你用\string&
by&
和\string\\
by \\
(或\tabularnewline
) 替换,并且小心扩展,则不需要此步骤。然后,事实证明,&
在括号外从未见过 (仅在\def\...{...&...}
括号内),这就是 TeX 不会阻塞的原因。
\tokenize
EDIT2:LaTeX3 具有与(即\tl_gset_rescan:Nnn
和朋友)类似的功能,并且它们具有与\tokenize
(即用户提供的参数并不总是隐藏在括号后面)相同的“错误”。截至 12 月 18 日(今天),该问题已在 svn 中得到修复。
答案2
尝试以下代码,其中:
和,
被 替换为&
:
\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}
\newcommand\foo[1]{%
\saveexpandmode\expandarg
\StrSubstitute{\noexpand#1}:&[\fooo]%
\StrSubstitute\fooo,&[\fooo]%
\StrSubstitute\fooo-{\noexpand\\}[\fooo]%
\restoreexpandmode\[\begin{matrix}\fooo\end{matrix}\]}
\begin{document}
\foo{1:2-2:3-x,y}
\end{document}
答案3
您可以尝试以下方法:
\documentclass[]{article}
\usepackage{mathtools}
\usepackage{xstring}
\newcommand{\foo}[1]{%
\begingroup
\catcode`\&=12
\noexpandarg
\StrSubstitute{#1}{-}{\tabularnewline}[\fooo]
\expandarg
\StrSubstitute{\fooo}{:}{&}[\fooo]
\expandafter\endgroup
\fooo}
\begin{document}
\[\begin{matrix}
\foo{1:2-2:3-4444:55555}
\end{matrix}\]
\end{document}