![使用 l3 正则表达式,如何捕获命令并将其替换为其名称?](https://linux22.com/image/474392/%E4%BD%BF%E7%94%A8%20l3%20%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%8C%E5%A6%82%E4%BD%95%E6%8D%95%E8%8E%B7%E5%91%BD%E4%BB%A4%E5%B9%B6%E5%B0%86%E5%85%B6%E6%9B%BF%E6%8D%A2%E4%B8%BA%E5%85%B6%E5%90%8D%E7%A7%B0%EF%BC%9F.png)
我有一个包含命令的 clist 形式的输入,例如{\my_cmd1,\my_xx_cmd2,\cmd3}
。我首先遍历此列表并删除逗号、反斜杠\
等。
我将输出保存在 |tl| 中。我想删除下划线“_”,但由于失败,我尝试使用正则表达式。这几乎适用于所有情况,也许是一种更好的方法。我怎样才能删除\
使用正则表达式并只保留命令的名称?
\documentclass{article}
\usepackage{xcolor}
\begin{document}
\makeatletter
\ExplSyntaxOn
\cs_set:Npn\my_remove_backslash_comma_and_space:n #1
{
\clist_set:Nn\l_tmpa_clist{#1}
\clist_map_inline:Nn\l_tmpa_clist
{
\expandafter\@gobble\string##1;
}
}
\cs_gset:Npn\test:n#1
{
\tl_gset:Nn\l_tmpb_tl{\my_remove_backslash_comma_and_space:n{#1}}
\tl_use:N\l_tmpb_tl
}
\ttfamily
%\tl_set:No\l_tmpa_tl{\test:n{\my_var:NTF, \my_othervar:n}}
\tl_set:No\l_tmpa_tl{my_var:NTF}
% Replace underscores
\regex_replace_all:nnN
{ (_)}
{/}\l_tmpa_tl
\par\tl_use:N\l_tmpa_tl
\regex_replace_all:nnN
{(NTF)}
{FALSE}\l_tmpa_tl
\par\tl_use:N\l_tmpa_tl
\ExplSyntaxOff
\makeatother
\end{document}
答案1
您对代码中函数和变量的扩展有很多误解。这对于评论来说太多了,所以我首先将它们总结为答案的一部分,然后再给出真正的答案,即如何删除下划线。
\tl_gset:Nn
不应在上使用\l_tmpb_tl
,因为那是一个局部变量,而应使用局部赋值,例如\tl_set:Nn
局部变量。\tl_(g)set:Nn
并且其他分配(\clist_set:Nn
例如)是不可扩展的,应该定义使用它们的函数protected
,例如\cs_gset_protected:Npn \test:n
。最好使用
\cs_new:Npn
它来定义函数、使用\cs_set:Npn
和朋友,仅当您要更改已经使用先前变体分配的宏的定义new
,或者在临时辅助宏的组内使用。所以\cs_new_protected:Npn \test:n
和类似。如果只需要
clist
单个循环,则使用\clist_map_inline:nn
而不是\clist_set:Nn ... \clist_map_inline:Nn
。\tl_set:No
将扩展\test:n
一次,它不会设置\l_tmpa_tl
为的最终结果\my_remove_backslash_comma_and_space:n
,而只会设置为其扩展的一步(因此它以 开始\clist_set:Nn
),但设置为最终结果根本是不可能的,因为\my_remove_backslash_comma_and_space:n
是不可扩展的。
现在来看看为什么你无法_
轻易删除的原因:在 a 之后,\string
下划线属于其他类别(因此为 12),但_
的内部\ExplSyntaxOn
属于字母类别(因此为 11),文档级别的下划线属于数学下标类别(因此为 8)。如果你想使用tl
函数来删除它们,你应该使用 的内容作为替换模式。但是如果你使用函数而不是,\c_underscore_str
那么你的工作会更轻松,因为你的内容无论如何都是字符串(或者至少你希望它们变成字符串)。l3str
l3tl
但情况更糟,因为当您使用 -call 调用时,\regex_replace_all:nnN
其内容\l_tmpa_tl
不包含任何下划线\test:n
(参见上文,您没有扩展\string
任何标记,因为您的函数没有扩展,而且即使您尝试这样做,它也是无法扩展的,而且您很可能会收到错误)。
要将单个变量设置为解析结果,您有两个选择:要么构建一个完全可扩展的函数并e
对其使用 -type 扩展,要么构建一个设置变量并对其进行操作的函数。以下显示了这两种方法:
\documentclass{article}
\usepackage{etl}
\ExplSyntaxOn
\str_new:N \l__yannisl_tmpa_str
\cs_new_protected:Npn \yannisl_unexp_remover:Nn #1#2
{
\str_clear:N \l__yannisl_tmpa_str
\clist_map_inline:nn {#2}
{ \str_put_right:Ne \l__yannisl_tmpa_str { \cs_to_str:N ##1 } }
\str_replace_all:Nnn \l__yannisl_tmpa_str { _ } {}
\str_set_eq:NN #1 \l__yannisl_tmpa_str
}
\cs_generate_variant:Nn \etl_new_replace_all:Nn { NV }
\etl_new_replace_all:NV \__yannisl_exp_remover_underscore:nn \c_underscore_str
\cs_generate_variant:Nn \__yannisl_exp_remover_underscore:nn { e }
\cs_new:Npn \yannisl_exp_remover:n #1
{ \clist_map_function:nN {#1} \__yannisl_exp_remover_aux:n }
\cs_new:Npn \__yannisl_exp_remover_aux:n #1
{ \__yannisl_exp_remover_underscore:en { \cs_to_str:N #1 } {} }
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\ttfamily
\yannisl_unexp_remover:Nn \l_tmpa_str { \my_var:NTF, \my_othervar:n }
\token_to_meaning:N \l_tmpa_str
\par
\str_set:Ne \l_tmpa_str
{ \yannisl_exp_remover:n { \my_var:NTF, \my_othervar:n } }
\token_to_meaning:N \l_tmpa_str
\ExplSyntaxOff
\end{document}