
我有一個以逗號分隔的字串清單key=value
。我想根據鍵提取值。有點像
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
目的是這將產生字串baz
.
我怎樣才能做到這一點?
答案1
您可以定義一個自訂鍵值解析器(假設鍵集應該是可變的):
\documentclass{article}
\makeatletter
\def\LookUpValue#1#2#3{%
\@tempswafalse
\gdef\LookUpValue@false{#3}%
\xdef\@tempa{#1}%
\LookUpValue@#2,\@end,}
\def\LookUpValue@#1,{%
\ifx#1\@end
\if@tempswa\@tempc\else\LookUpValue@false\fi
\else
\LookUpValue@@#1\@nil\expandafter\LookUpValue@\fi}
\def\LookUpValue@@#1=#2\@nil{%
\edef\@tempb{#1}%
\ifx\@tempa\@tempb\gdef\@tempc{#2}\@tempswatrue\fi
}
\makeatother
\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\textit{\LookUpValue{d}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}}
\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\end{document}
附錄一
如果你看一下@egreg的答案,你會發現有一個非常好的功能,它允許你將結果儲存\LookUpValue
到巨集中而不需要列印它。這是在 LaTeX2e 中實現此目的的一種方法(給出我的主要解決方案):
\documentclass{article}
\makeatletter
\def\LookUpValue{\kernel@ifnextchar[\@LookUpValue{\@LookUpValue[\@tempa]}}
\def\@LookUpValue[#1]#2#3{%
\@tempswafalse
\begingroup
\escapechar\m@ne
\xdef\luv@namespace{\string#1}%
\endgroup
\xdef\reserved@a{#2}%
\expandafter\LookUpValue@#3,\@end,}
\def\LookUpValue@#1,{%
\ifx#1\@end
\if@tempswa\@nameuse{@tempa}\let\@tempa\relax
\expandafter\expandafter\expandafter\@gobble\fi%
\else
\LookUpValue@@#1\@nil\expandafter\LookUpValue@\fi}
\def\LookUpValue@@#1=#2\@nil{%
\edef\reserved@b{#1}%
\ifx\reserved@a\reserved@b\@namedef{\luv@namespace}{#2}\@tempswatrue\fi
}
\makeatother
\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\def\mypreset{a=foo,b=bar,c=baz,d=zyyzx}
\LookUpValue[\myval]{d}{\mypreset}{}
\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\textsc{\myval}
\end{document}
附錄二
但是,如果您嘗試提取值的鍵集在整個文件中是固定的,則有以下更簡單的方法:
\documentclass{article}
\usepackage{keyval}
\makeatletter
\newcommand\newspraffkey[1]{\define@key{spraffkeys}{#1}{\@namedef{value_of_#1}{##1}}}
\newcommand\LookUpValue[2]{%
\begingroup
\setkeys{spraffkeys}{#2}%
\@nameuse{value_of_#1}%
\expandafter\ifx\csname value_of_#1\endcsname\relax\else\expandafter\@gobbleaftergroup\fi
\endgroup
}
\def\@gobbleaftergroup{\aftergroup\@gobble}
\makeatother
\newspraffkey{a}
\newspraffkey{b}
\newspraffkey{c}
\newspraffkey{d}
\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\LookUpValue{d}{a=foo,b=bar,c=baz}{error:notfound}
\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\end{document}
答案2
property
使用語法填入清單expl3
並尋找相關鍵值對的版本。也許不是最快的方法,但很容易使用。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\cs_generate_variant:Nn \prop_put:Nnn {Nxn,Nxx}
\NewDocumentCommand{\LookUpValue}{mmm}{%
\seq_set_from_clist:Nn \l_tmpa_seq {#2}
\seq_map_inline:Nn \l_tmpa_seq {% Mapping through the sequence
\seq_set_split:Nnn \l_tmpb_seq {=} {##1}
% Filling the property list
\prop_put:Nxx \l_tmpa_prop {\seq_item:Nn \l_tmpb_seq {1}} {\seq_item:Nn \l_tmpb_seq {2}}
}
% Look if #1 is in the property list and display the value, otherwise #3
\prop_if_in:NnTF \l_tmpa_prop {#1} {\prop_item:Nn \l_tmpa_prop {#1}} {#3}
}
\ExplSyntaxOff
\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\LookUpValue{foobar}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\end{document}
答案3
expl3
以下程式碼使用;中的鍵值函數這裡我利用“未知密鑰”,如果我提前知道密鑰,可以做得更好。
如果給出了可選參數,它應該是一個將被(重新)定義到結果的控制序列。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\LookUpValue}{ommm}
{
\str_set:Nn \l_spraff_given_key_str { #2 }
\tl_clear:N \l_spraff_output_tl
\keys_set:nn { spraff/random } { #3 }
\tl_if_empty:NT \l_spraff_output_tl
{
\tl_set:Nn \l_spraff_output_tl { #4 }
}
\IfNoValueTF{#1}
{ \tl_use:N \l_spraff_output_tl }
{ \tl_set_eq:NN #1 \l_spraff_output_tl }
}
\keys_define:nn { spraff/random }
{
unknown .code:n =
\str_if_eq:NNT \l_spraff_given_key_str \l_keys_key_tl
{
\tl_set:Nn \l_spraff_output_tl { #1 }
}
}
\ExplSyntaxOff
\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\LookUpValue[\temp]{a}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\texttt{\meaning\temp}
\end{document}