我有一個用逗號分隔的字串。我想獲取每個元素並應用命令。我有以下內容,有效。
\documentclass[12pt]{article}
\usepackage[trim]{tokenizer}
\newcommand{\cadd}[1]{
\def\Source{#1}
\whiledo{\not\equal{\Source}{}}
{
\GetTokens{TokenOne}{TokenTwo}{\Source}
\textbf{\TokenOne}
\let\Source\TokenTwo
}
}
\begin{document}
\cadd{a,b,c}
\end{document}
但我想要以下內容
\documentclass[12pt]{article}
\usepackage[trim]{tokenizer}
\newcommand{\cadd}[1]{
\whiledo{\not\equal{#1}{}}
{
\GetTokens{TokenOne}{TokenTwo}{#1}
\textbf{\TokenOne}
\let\#1\TokenTwo
}
}
\begin{document}
\cadd{a,b,c}
\end{document}
但\let\#1\TokenTwo
給了一個錯誤。我怎樣才能#1
使用\let
答案1
#1
在第一次呼叫巨集時被替換。如果宏\cadd
\newcommand{\cadd}[1]{
\whiledo{\not\equal{#1}{}}
{
\GetTokens{TokenOne}{TokenTwo}{#1}
\textbf{\TokenOne}
\let\#1\TokenTwo
}
}
稱為\cadd{a,b,c}
,則變為:
<space>
\whiledo{\not\equal{a,b,c}{}}<space>
{<space>
\GetTokens{TokenOne}{TokenTwo}{a,b,c}<space>
\textbf{\TokenOne}<space>
\let\#1\TokenTwo
}<space>
- 這行
\let\#1\TokenTwo
由\let
賦值\let\#=1
和組成\TokenTwo
。#1
僅在巨集擴充中用第一個參數取代。 有許多空格標記(由行尾引起):
- 第一個在垂直模式下被忽略,因為該段落尚未開始。
\whiledo
如果將循環體作為無分隔參數讀取,則第二個被忽略。- 第三個和第四個將出現在輸出中。
- 由於段落結尾,最後一個被刪除。
透過使用註解字元可以避免行尾出現空格標記,如以下範例所示。
有許多用於逗號分隔清單的解析器。其中之一是由包包提供的kvsetkeys
:
\documentclass[12pt]{article}
\usepackage{kvsetkeys}
\makeatletter
\newcommand{\cadd}[1]{%
\comma@parse{#1}{\caddentry}%
}
\newcommand*{\caddentry}[1]{%
\textbf{[#1]}%
}
\makeatother
\begin{document}
\cadd{a,b,c}
\cadd{ a , b , c }
\cadd{abc, def, ghi}
\cadd{{ with spaces }, {a b c}}
\end{document}
答案2
Heiko 在這裡很好地介紹了細節。為了完整起見,使用 LaTeX3 逗號列表映射函數的解決方案\clist_map_inline:nn
\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\NewDocumentCommand { \cadd } { m }
{ \clist_map_inline:nn {#1} { [ \textbf {##1} ] } }
\ExplSyntaxOff
\begin{document}
\cadd{a,b,c}
\cadd{ a , b , c }
\cadd{abc, def, ghi}
\cadd{{ with spaces }, {a b c}}
\end{document}
基本概念與 Heiko 的答案非常相似:不必手動進行映射,而是使用預先建立的命令來處理查找清單末尾。