为什么这个 \regex_split:nnN 会导致错误并插入“{”?

为什么这个 \regex_split:nnN 会导致错误并插入“{”?

我正在expl3尝试一些高阶编程。在此示例中,我定义了一个环境,然后对该环境执行了一项操作:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{amsmath, amssymb}

\begin{document}

\ExplSyntaxOn
\prop_new:N \l_files_prop
\newcommand{\addConfig}[2]{
    \prop_put:Nnn \l_files_prop {#1} {{#2}}
}
\newcommand{\printConfig}[2]{
    \prop_get:NnN \l_files_prop {#1} \l__files
    \cs_generate_variant:Nn {\regex_split:nnN} {nVN}
    \regex_split:nVN {;} {\l__files} {\l__files_split_tl}
    %\seq_set_split:NnV \l__files_split_tl {o} {\l__files}
  
    %\seq_set_split:Nnn \l__cmd_tl {\textbackslash} {\tl_to_str:n #2}
    \seq_map_inline:Nn \l__files_split_tl {
        \use:c {\cs_to_str:N #2} {##1}\\
    } 
}

\ExplSyntaxOff

\addConfig{config1}{hello; world}
\addConfig{config2}{bye; world}
\addConfig{config3}{testFile.tex; testFile2.tex}

\noindent
\printConfig{config1}{\textit}
\printConfig{config2}{\textbf}
%\printConfig{config3}{\input}

\end{document}

正确结果是

结果1

但是,我得到了正确的输出以及以下错误:

! LaTeX3 Error: Missing brace inserted when splitting or extracting
(LaTeX3)        submatches.

For immediate help type H <return>.
 ...                                              
                                                  
l.75 \printConfig{config1}{\textit}
                                   

LaTeX was asked to do some regular expression operation, and the resulting
token list would not have the same number of begin-group and end-group tokens.
Braces were inserted: 1 left, 1 right.

我也不太明白为什么;我试着去理解本指南并与文档但我也找不到任何关于为什么会发生这种情况的信息。

我该如何重写代码来消除这个错误?而且(更重要的是),为什么会出现这个错误?

答案1

您在命令中添加了一组虚假的括号\prop_put:Nnn

\prop_put:Nnn \l_files_prop {#1} {{#2}}

将其更改为

\prop_put:Nnn \l_files_prop {#1} {#2}

解决了问题。出现此错误的原因是,对于一个标记列表{hello;world},在 处拆分它将;在每个项目中留下不平衡的括号({helloworld}),这是非法的,因此l3regex插入一些括号来平衡标记列表。

我还改变了一些内容以更好地符合expl3标准:

  • 所有变量都应该声明,因此您需要一个\tl_new:N \l__files_split_tl和一个\tl_new:N \l__files(有关这一点请参阅下一项);
  • 变量应该\⟨scope⟩_⟨module⟩_⟨name⟩_⟨type⟩ 这样命名\l__files,这是一个糟糕的名字。类似这样的名字\l__fabian_files_tl更好,假设fabian是模块;
  • \cs_generate_variant:Nn每个变体只能执行一次,因此您可以将其移到命令之外;
  • 假设#2是一个控制序列,\use:c {\cs_to_str:N #2}与刚才的效果相同#2,因此可以简化;
  • 的输出\regex_split:nnN是一个seq变量,而不是tl,所以您应该使用它;
  • [奖金]如果你只是想在 a 处进行拆分,则根本;不需要。你可以使用 lineregex来代替它(主要区别在于它将保留项目周围的空格,但会修剪空格)。\regex_split:nVN\seq_set_split:NnV \l__fabian_files_split_seq { ; } \l__fabian_files_tl\regex_split:nVN\seq_set_split:NnV

代码如下:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xparse}
\usepackage{amsmath, amssymb}

\begin{document}

\ExplSyntaxOn
\prop_new:N \l_fabian_files_prop
\tl_new:N \l__fabian_files_tl
\seq_new:N \l__fabian_files_split_seq
% \cs_generate_variant:Nn \regex_split:nnN { nV }

\NewDocumentCommand \addConfig { mm }
  { \prop_put:Nnn \l_fabian_files_prop {#1} {#2} }
\NewDocumentCommand \printConfig { mm }
  {
    \prop_get:NnN \l_fabian_files_prop {#1} \l__fabian_files_tl
    % \regex_split:nVN { ; } \l__fabian_files_tl \l__fabian_files_split_seq
    \seq_set_split:NnV \l__fabian_files_split_seq { ; } \l__fabian_files_tl
    \seq_map_inline:Nn \l__fabian_files_split_seq { #2 {##1} \\ }
  }

\ExplSyntaxOff

\addConfig{config1}{hello; world}
\addConfig{config2}{bye; world}
\addConfig{config3}{testFile.tex; testFile2.tex}

\noindent
\printConfig{config1}{\textit}
\printConfig{config2}{\textbf}
%\printConfig{config3}{\input}

\end{document}

相关内容