![解析 \foreach 的逗号分隔列表](https://linux22.com/image/455691/%E8%A7%A3%E6%9E%90%20%5Cforeach%20%E7%9A%84%E9%80%97%E5%8F%B7%E5%88%86%E9%9A%94%E5%88%97%E8%A1%A8.png)
\foreach
我在逗号分隔的列表中使用 PGF,其中的项目可能包含空格;{...}
如果每个项目包含空格,则可以将其括起来,这样就可以了。现在,当列表中只有一个项目时会发生什么?奇怪的是,空格在这里有(对我来说意想不到的)影响。
如果能给出解释,或者更好的是,提供一种避免这种输入脆弱性的方法,我将不胜感激。
这是正确解析的:
\fooList{items={{foo, foo}
}
}
但不是这个:
\fooList{items={{foo, foo}
}}
或者这个:
\fooList{items={{foo, foo}}}
\documentclass{article}
\usepackage{pgffor}
\pgfkeys{
/foo/.is family,
/foo,
items/.store in=\fooItems,
items/.initial=\undefined
}
\newcommand{\fooList}[1]{
\pgfkeys{/foo/.cd,#1}
\begin{enumerate}
\foreach [var=\content] in \fooItems{\item\content}
\end{enumerate}
}
\parindent=0pt
\begin{document}
Comma-separated list works fine for two items:
\fooList{
items={
{foo, foo},
{bar, bar}
}
}
Single item is understood when written with trailing newlines
\fooList{items={{foo, foo}
}
}
It gets incorrectly split when written like this:
\fooList{items={{foo, foo}
}}
And also when fully compacted:
\fooList{items={{foo, foo}}}
\end{document}
答案1
恐怕你对这些错误无能为力...如果你想坚持下去,pgfkeys
有两种可能性没有可行的解决方案:
- 总是在开括号前或闭括号后留一个空格(
\fooItems{items={{one,two}} }
或\fooItems{items= {{one,two}}}
-- 或两者皆有) - 在值周围添加一个额外的括号 (
\fooItems{items={{{one,two}}}}
)
编辑:不幸的是,这仍然不正确,因为pgfkeys
,如果值周围没有空格,它会过多地删除一组括号(这可以通过两个建议来解决)然后它可能会删除一秒将值转发给.store in
处理程序定义的底层命令时使用大括号(哎哟!)
但请注意,有几个可用的 key=value 解析器没有那个括号错误(并且也可能提供 csv 循环宏):
expkv
kvsetkeys
l3keys
(该语言中的 LaTeX 内核的一部分expl3
)\DeclareKeys
/\SetKeys
(LaTeX 内核的一部分)
下面使用expkv
(免责声明:我是包作者)和l3keys
(语言expl3
)演示了您的代码:
\documentclass{article}
\usepackage{expkv-def}
\ekvdefinekeys{foo}
{
store items = \fooItems
,initial items = \undefined
}
\newcommand\fooList[1]
{%
\ekvset{foo}{#1}%
\begin{enumerate}
% no automatic detection of a variable storing the list, so we need to
% manually expand it.
\expandafter\ekvcsvloop\expandafter\item\expandafter{\fooItems}%
\end{enumerate}
}
\ExplSyntaxOn
\keys_define:nn { eudoxos / foo }
{
items .clist_set:N = \l__eudoxos_items_clist
,items .initial:n = \undefined
}
\NewDocumentCommand \FooList { m }
{
\keys_set:nn { eudoxos / foo } {#1}
\begin{enumerate}
\clist_map_function:NN \l__eudoxos_items_clist \item
\end{enumerate}
}
\ExplSyntaxOff
\parindent=0pt
\begin{document}
\section{Using \texttt{expkv}}
Comma-separated list works fine for two items:
\fooList{
items={
{foo, foo},
{bar, bar}
}
}
Single item is understood when written with trailing newlines
\fooList{items={{foo, foo}
}
}
It gets incorrectly split when written like this:
\fooList{items={{foo, foo}
}}
And also when fully compacted:
\fooList{items={{foo, foo}}}
\clearpage
\section{Using \texttt{l3keys}}
Comma-separated list works fine for two items:
\FooList{
items={
{foo, foo},
{bar, bar}
}
}
Single item is understood when written with trailing newlines
\FooList{items={{foo, foo}
}
}
It gets incorrectly split when written like this:
\FooList{items={{foo, foo}
}}
And also when fully compacted:
\FooList{items={{foo, foo}}}
\end{document}