这花了我比预期更长的时间来完成本来应该非常简单的任务。我需要一种方法来将 tokenlist 变成小写并删除空格。但str_lowercase:N
不存在!尝试生成变体失败了。我尝试过的任何组合\MakeLowercase
都\tl_remove_all:Nn
不能很好地协同工作。我最终使用了两个辅助函数来完成这项工作。解决方案到目前为止有效。我把这个问题分成两部分,一是记录我的解决方案,二是询问是否有更好的方法,最好只使用 expl3。
% this function exists to simplify the call for the other, reducing the number of arguments to 1.
\cs_new_protected:Npn \tl_lowercase:N #1
{ \bob_tl_lowercase:No #1 #1 }
% this function and its generated varient cause arguement 2 to expand once
% so it can be accepted by \str_lowercase:n, then sets it to itself
\cs_new_protected:Npn \bob_tl_lowercase:Nn #1#2
{ \tl_set:Nx #1 { \str_lowercase:n {#2} } }
\cs_generate_variant:Nn \bob_tl_lowercase:Nn { No }
% just a example use case function
\tl_new:N \itemfilename
\NewDocumentCommand{\getfilename}{s+m} {
\tl_set:Nn \itemfilename {#2}
\tl_remove_all:Nn \itemfilename {~}
\tl_lowercase:N \itemfilename
\tl_show:N \itemfilename
}
答案1
有,\str_lowercase:n
而且它是完全可扩展的,但是(正如约瑟夫正确指出的)还有更好的\str_foldcase:n
。
\str_new:N \l_bob_itemfilename_str
\NewDocumentCommand{\getfilename}{m}
{
\str_set:Nx \l_bob_itemfilename_str { \str_foldcase:n { #1 } }
\str_replace_all:Nnn \l_bob_itemfilename_str { ~ } { }
\str_show:N \l_bob_itemfilename_str
}
\getfilename{SaMPleName WITH upperCase and SPACES}
控制台显示
> \l_bob_itemfilename_str=samplenamewithuppercaseandspaces.
改进的版本可以管理已经构建的令牌列表或字符串:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\getfilename}{sm}
{
\IfBooleanTF { #1 }
{
\bob_filename_get:V #2
}
{
\bob_filename_get:n { #2 }
}
}
\str_new:N \l_bob_filename_item_str
\cs_new_protected:Nn \bob_filename_get:n
{
\str_set:Nx \l_bob_filename_item_str { \str_foldcase:n { #1 } }
\str_replace_all:Nnn \l_bob_filename_item_str { ~ } { }
\str_show:N \l_bob_filename_item_str
}
\cs_generate_variant:Nn \bob_filename_get:n { V }
\getfilename{SaMPleName WITH upperCase and SPACES}
\def\test{SaMPleName WITH upperCase and SPACES}
\getfilename*{\test}
无论哪种情况,控制台都会有
> \l_bob_filename_item_str=samplenamewithuppercaseandspaces.
答案2
环顾四周后,我认为这是该问题的正确答案。
\tl_set:Nx \itemfilename { \str_foldcase:V \itemfilename }
一个重要的信息是\str_foldcase
“该过程的结果留在输入流中。”即使手册中没有提到,这对于 str_lowercase 似乎也是如此。
仔细阅读手册后发现,“[ str_lowercase:n
] 函数不应用于不区分大小写的比较”。
然而,我在以下方面也取得了成功。
\cs_generate_variant:Nn \str_lowercase:n {V}
\tl_set:Nx \itemfilename { \str_lowercase:V \itemfilename }.
答案3
这是一种无需 expl3 的方法……相反,它使用标记循环来删除空格并将字符引导至宏\explowercase
。
这里设置了预扩展其参数,以便它可以与字符串或\def
字符串一起使用。
\documentclass{article}
\def\explowerchar#1{%
\ifcase\numexpr`#1-`A\relax
a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m\or
n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z\else
#1\fi
}
\usepackage{tokcycle}
\Characterdirective{\addcytoks[x]{\explowerchar{#1}}}
\Spacedirective{}
\newcommand\getfilename[1]{\expandedtokcyclexpress{#1}\the\cytoks}
\begin{document}
\getfilename{SaMPleName WITH upperCase and SPACES}
\def\test{SaMPleName WITH upperCase and SPACES}
\getfilename{\test}
\end{document}