在此评论(以下复制时未做任何努力以保留格式):
可能值得指出为什么会发生这种情况。LaTeX 中可选参数的 [ 和 ] 括号不如 TeX 的 { ... } 括号那么强大。特别是,[ 与下一个 ] 匹配,后者与其处于同一组(就 { ... } 分组而言)。它不会查看 ] 是否应该匹配中间的 [。解决方案是(如 Andrey 所说)通过将任何中间的 [ 和 ] 括在括号中来确保它们位于不同的 TeX 组中。– Loop Space 2011 年 3 月 21 日 8:09
据称 LaTeX 解析方括号的方式与 TeX 处理花括号的方式不同。这有什么设计原因吗?只是因为这样编程更简单吗?其他 TeX 标准变体(XeTeX、LuaTeX 等)也是这样吗?
答案1
TeX 仅识别两个分组字符。这些是分配了 catcode 1(开始组)和 2(结束组)的字符。默认情况下,它们分别是{
和}
。[
和]
字符只是分配给 catcode 12 的常规非字母字符。有关 TeX catcode 的更多信息,请参阅类别代码是什么?。
因此,只有括号(或者更确切地说,catcode 1 和 2 个字符)会被匹配;其他所有内容,包括由[
]
或(
)
或分隔的参数|
(使用一些真实示例)的处理方式完全不同,通常使用类似 TeX 的分隔参数定义,它不能直接处理嵌套。有关分隔参数的更多信息,请参阅TeX 如何查找分隔参数?和为什么 TeX 会删除分隔参数周围的括号?。
正如 egreg 在评论中指出的那样,使用该xparse
包定义的命令能够处理嵌套的[ ]
可选参数。这里有一个小例子来展示它们是如何工作的。
这里我定义了两个看似相同的命令,一个使用\newcommand
,另一个使用xparse
's \NewDocumentCommand
。它们每个都接受一个可选参数。我使用颜色来显示命令如何解析参数。
为了展示每个命令如何嵌套使用,[ ]
我们可以尝试将第一个可选参数设为字符串[Arg1]
。 如果我们的命令正常工作,它应该使字符串变为[Arg1]
红色,将字符串变为[Arg2]
蓝色。
\documentclass{article}
\usepackage{xparse}
\usepackage{xcolor}
\newcommand{\regularcmd}[2][]{{\color{red}#1}{\color{blue}#2}}
\NewDocumentCommand{\xparsecmd}{o m}{{\color{red}#1}{\color{blue}#2}}
\begin{document}
\begin{enumerate}
\item\regularcmd[[Arg1]]{[Arg2]}
\item\regularcmd[{[Arg1]}]{[Arg2]}
\item\xparsecmd[[Arg1]]{[Arg2]}
\item\xparsecmd[{[Arg1]}]{[Arg2]}
\end{enumerate}
\end{document}
从输出项 1 中可以看出,常规定义的命令无法做到这一点。相反,它会在]
遇到第一个可选参数时停止解析,然后将下一个标记(在本例中为结束标记)]
作为第二个参数,因此只有]
以蓝色显示,而我们期望的蓝色根本没有颜色。如果我们希望此命令正常工作,则需要用[Arg1]
括号保护参数,以便]
解析可选参数时遇到的第一个是第二个]
。这就是输出项 2 所做的。
但是,定义的命令xparse
能够处理这种嵌套而不需要任何额外的括号,因此即使项 3 使用与项 1 相同的表面语法,输出项 3 和 4 都显示我们期望的输出。