使用 xstring 的 StrSubstitute 激活空格

使用 xstring 的 StrSubstitute 激活空格

我有一些文本,我想使用xstring\StrSubstitute方法进行预处理(基本上是用简单的命令(如foobarby )替换某些关键字\emph{foobar})。有两个附带条件使这变得困难(至少我还没能弄清楚如何做到这一点)。一方面,我需要在模式\StrSubstitute下运行noexpandarg,另一方面,我想使用活动空格来打印出遵循空格的输入。我知道有诸如listings或 之类的环境verbatim,但这些环境不符合我的想法:最终,这样预处理的字符串应该进入 ( amsmath)align环境。

这就是我所拥有的

\documentclass{article}

\usepackage{xstring}

\begingroup
\catcode`\@=\active
\lccode`\@=`\ % At-sign is a space
\lowercase{%
  \endgroup
  \newenvironment{withspaces}{%
    \catcode`\ =\active % Space active
    \let@=~%
   }{ 
}}

\begin{document}

\def\foo{foo}
\begin{withspaces}
There is space before        \foo foo
\end{withspaces}

\begin{withspaces}
\StrSubstitute{There is space before        \foo foo}{foo}{bar}
\end{withspaces}

\noexpandarg % in order to first run the string substitution and only then expand \foo
\StrSubstitute{There is space before        \foo foo}{foo}{bar}

% The following breaks down to the noexpandarg flag
\begin{withspaces}
%\StrSubstitute{There is space before        \foo foo}{foo}{bar}
\end{withspaces}


\end{document}

环境withspaces(改编自 Joseph 的回答遵循空间的环境) 似乎在文本模式和数学模式下都能正常工作。 第一次使用 时的效果\StrSubstitute与 中相同fullyexpandmode。 但是,结果是首先\foo扩展 ,然后替换为 ,\StrSubstitute这就是为什么我认为我需要使用noexpandarg\StrSubstitute应该进行替换而不扩展\foo

单独来看,这个方法也很好用。也就是说,

\noexpandarg % in order to first run the string substitution and only then expand \foo
\StrSubstitute{There is space before        \foo foo}{foo}{bar}

得到所需的结果,但没有活动空格。一旦我尝试将两者结合起来(取消注释\StrSubstituteMWE 中的最后一个),我就陷入了

Argument of \@xs@behindspace has an extra }.
<inserted text> 
                \par 
l.33 \end
         {withspaces}

这就是我迷失的地方。

答案1

您可能需要查看使用以下方法的实现l3regex

\documentclass{article}

\usepackage{xstring}
\usepackage{xparse}
% \usepackage{l3tl-analysis} % uncomment for debugging

\newenvironment{withspaces}
 {\obeyspaces\begingroup\lccode`~=` \lowercase{\endgroup\let~}~}
 {}

\ExplSyntaxOn
\tl_new:N \l_arno_strsub_input_tl
\tl_new:N \l_arno_strsub_search_tl
\tl_new:N \l_arno_strsub_replace_tl

\NewDocumentCommand{\strsub}{mmm}
 {
  \tl_set:Nn \l_arno_strsub_input_tl { #1 }
  \tl_set:Nn \l_arno_strsub_search_tl { #2 }
  \tl_set:Nn \l_arno_strsub_replace_tl { #3 }
  \regex_replace_all:nnN
   { \u{l_arno_strsub_search_tl} }
   { \u{l_arno_strsub_replace_tl} }
   \l_arno_strsub_input_tl
  %\tl_show_analysis:N  \l_arno_strsub_input_tl % uncomment for debugging
  \tl_use:N \l_arno_strsub_input_tl
 }
\ExplSyntaxOff

\begin{document}

\def\foo{foo}
\begin{withspaces}
There is space before        \foo foo
\end{withspaces}

\begin{withspaces}
\strsub{There is space before        \foo foo}{foo}{bar}
\end{withspaces}

\strsub{There is space before        \foo foo}{foo}{bar}

\begin{withspaces}
\strsub{Some  spaces  \foo foo}{foo}{\textbf{foo}}
\end{withspaces}

\end{document}

搜索和替换字符串存储在标记列表中,因此它们可以“按原样”用于正则表达式业务。

正如您在最后一个例子中看到的,只有的明确外观foo被替换了。

如果取消注释标记为“用于调试”的行,您将在终端中看到正则表达式替换后的字符串表示。

(对于 TeX Live 2017 之前的版本,您还需要\usepackage{l3tl-analysis}\usepackage{l3regex}才能\usepackage{xparse}使用此功能。)

在此处输入图片描述

答案2

您可以定义\dospaces为宏的前缀\StrSubstitute

\def\dospaces\StrSubstitute{\bgroup\catcode`\ =13 \let\protect=\noexpand \dospacesA}
\def\dospacesA#1{\xdef\tmp{#1}\egroup \expandafter\StrSubstitute\expandafter{\tmp}}

%% usage:

\dospaces\StrSubstitute{There is space before        \foo foo}{foo}{bar}

相关内容