LaTeX3 正则表达式能够匹配行首的字符吗?

LaTeX3 正则表达式能够匹配行首的字符吗?

我想使用 LaTeX3 正则表达式从文本中提取“行”,如下所示:

- First line
- second line ending with \LaTeX
- third line with - in the middle
- fourth line that
goes on for a bit

我所说的“行”是指以-“物理行”开头的破折号开头的文本,一直延续到下一个这样的破折号或字符串的末尾。

我的第一个猜测是,类似下面的方法可以起作用:

\regex_split:nVN {  [\f\n\r]\s+-\s+  } { \Lines } \l_tmp_seq

我的理解是,这应该匹配一个“换行符”,后面跟着-一个两边都是空格的字符。不幸的是,这很糟糕,只产生了一个匹配:

enter image description here

由于这不起作用,我想我会尝试一种非常简单的方法,只需在空白包围的破折号上拆分字符串-。这会在行上产生错误的结果,例如上面的第三行,但我可以--在行的中间使用,所以这是一个可行的替代方案。由于\s匹配空白,以下应该在上拆分行-

\regex_split:nVN { \s+-\s+  } { \Lines } \l_tmp_seq

这样比较好,但是结果仍然不完美,因为除了第 3 行预期的问题之外,\LateX在行尾出现 也会引起混淆,\regex_split大概是因为宏往往会吞掉空格:

enter image description here

我发现的最佳解决方案是使用:

\regex_split:nVN { \B-\B } { \Lines } \l_tmp_seq

这将产生我期望从最后一个正则表达式获得的输出:

enter image description here

也就是说,我们-在第三行中间得到了不想要的匹配,但除此之外没有问题。

问题是否存在不返回任何错误匹配的正则表达式?允许初始和/或最终匹配空序列。

[附言:我并不担心上面的“空”初始序列,因为我知道可以使用

\seq_pop_left:NN \l_tmp_seq \l_tmpa_tl % pop initial blank

当然,终止空序列可以使用几乎完全相同的方式处理\seq_pop_right:NN。]

以下是生成上述示例的完整 MWE:

\documentclass{article}
\usepackage{xparse}
\parindent=0pt

\newcommand\BS{$\backslash$}
\newcommand\Test[1]{\textbf{Testing:}\quad\texttt{#1}}
\begin{document}

\newcommand\Lines{
    - First line
    - second line ending with \LaTeX
    - third line with -- in the middle
    - fourth line that
    goes on for a bit
}

\ExplSyntaxOn
\seq_new:N \l_tmp_seq
\cs_generate_variant:Nn \regex_split:nnN { nVN }

\Test{[\BS f\BS n\BS r]\BS s+-\BS s+}
\regex_split:nVN { [\f\n\r]\s+-\s+  } { \Lines } \l_tmp_seq
\begin{itemize}\item\seq_use:Nn \l_tmp_seq {\item }\end{itemize}

\Test{\BS s-\BS s}
\regex_split:nVN { \s-\s  } { \Lines } \l_tmp_seq
\begin{itemize}\item\seq_use:Nn \l_tmp_seq {\item }\end{itemize}

\Test{\BS B-\BS B}
\regex_split:nVN { \B-\B  } { \Lines } \l_tmp_seq
\begin{itemize}\item\seq_use:Nn \l_tmp_seq {\item }\end{itemize}

\ExplSyntaxOff

\end{document}

在正则表达式中转义-也无济于事。

最后,问题可能是在定义时删除了换行符\Lines。据我所知,这是可以的,因为上面的代码给出了类似的输出。特别是,如果我使用:

\documentclass{article}
\usepackage{xparse}
\parindent=0pt

\begingroup\obeylines
\gdef\Lines{
    - First line
    - second line ending with \LaTeX
    - third line with -- in the middle
    - third line that
    goes on for a bit
}
\endgroup

\begin{document}

  \ExplSyntaxOn
  \seq_new:N \l_tmp_seq
  \cs_generate_variant:Nn \regex_split:nnN { nVN }
  \regex_split:nVN { [\f\n\r]\s+\-\s+  } { \Lines } \l_tmp_seq

  Sequence~length:~ \seq_count:N \l_tmp_seq.
  \begin{itemize}\item\seq_use:Nn \l_tmp_seq {\item }\end{itemize}
  \ExplSyntaxOff

\end{document}

然后我得到输出:

enter image description here

在实践中,我得到的\Lines\BODY环境环境,所以我实际上没有这个定义的奢侈......

答案1

您需要 obelines 或类似的东西,这样换行符就不会消失。下面将按需要(几乎)拆分行。\^^M也可以使用\r(我只使用了第一个,因为\show\Lines显示了^^M)。

这将创建以下序列:

The sequence \l_tmp_seq contains the items (without outer braces):
>  {First line}
>  {second line ending with \LaTeX }
>  {third line with -- in the middle}
>  {fourth line that^^Mgoes on for a bit^^M}.
<recently read> }

一个问题可能是第四项包含一个^^M可能不需要的换行符。

\documentclass{article}
\usepackage{xparse}
\parindent=0pt

\newcommand\BS{$\backslash$}
\newcommand\Test[1]{\textbf{Testing:}\quad\texttt{#1}}
\begin{document}

\begingroup
\obeylines
\gdef\Lines{
    - First line
    - second line ending with \LaTeX
    - third line with -- in the middle
    - fourth line that
    goes on for a bit
}

\endgroup

\ExplSyntaxOn
\seq_new:N \l_tmp_seq
\cs_generate_variant:Nn \regex_split:nnN { nVN }

\Test{}\verb+^^M\-+
\regex_replace_once:nnN { \A\^^M?\-\s* } {} \Lines %to get rid of the first ^^M
\regex_split:nVN { \^^M\-\s* } \Lines \l_tmp_seq

\begin{itemize}\item\seq_use:Nn \l_tmp_seq {\item }\end{itemize}


\ExplSyntaxOff

\end{document}

enter image description here

相关内容