编辑

编辑

我想定义一个环境(碰巧在一个类文件中),其内容在编写时显示在屏幕上,但它们也会被修改(例如使用包l3regex),然后写入文件。

我的具体要求是我想要一个solution环境(其中给出了问题的答案),但解决方案有一个由一系列\marks{...}命令给出的标记方案。写入文件的版本需要\marks{...}删除这些部分。

以下 mwe 代码基于这个帖子,在所需的上下文中正确执行我需要的正则表达式替换:

\documentclass{article}

\usepackage{l3regex}
\usepackage{environ}
\usepackage{marginnote}

\renewcommand\marks[1]{\marginnote{[#1]}}

\ExplSyntaxOn
\NewEnviron{solution}
 {
  \strip_marks:V \BODY
 }

\tl_new:N \solution_text_tl

\cs_new_protected:Nn \strip_marks:n
 {
  \tl_set:Nn \solution_text_tl { #1 }
  \solution_text_tl  % Inserts original text in the right place 
  \regex_replace_all:nnN { \c{marks}\cB\{ [0-9]* \cE\} } {   } \solution_text_tl
  \regex_replace_all:nnN { \c{marks} [0-9] } {   } \solution_text_tl
  \immediate\write\answerfile{\solution_text_tl}
  %\solution_text_tl <-- ***Regex done, how to write to file?***
 }
\cs_generate_variant:Nn \strip_marks:n { V }
\ExplSyntaxOff

\begin{document}
\newwrite\answerfile
\immediate\openout\answerfile=solution-no-marks.tex


\begin{solution}
This line has a \emph{mark} at the end of it.\marks{10}
\end{solution}


\immediate\closeout\answerfile
\end{document}

如上所述,此代码返回错误(与有关marginnote,但实际上这是因为在写入文件时,它扩展了\emph{...})。如果我删除环境\emph{...}中的solution,则代码将按预期进行编译。但是,solution在写入文件时,我确实需要保留环境中的控制序列。我尝试过,例如,包answers(或类似的其他解决方案,在某种程度上都依赖于verbatim),但是我该如何进行我想要的正则表达式替换?

答案1

这是你想要的吗?

输出到文件(我已经使用过\jobname-soln.tex):

This line has a \emph {mark} at the end of it.

输出为 PDF:

PDF

请注意,如果您的命令序列带有参数,则需要适当指定签名并给出参数:

\cs_new_protected:Npn \strip_marks:n #1

否则,您不能将参数传递给\strip_marks:n. With just\cs_new_protected:Nn,您可以定义\strip_marks:,但不能接受参数,并且您不能#1在定义中使用。

此外,为了符合 L3 语法规范,标记列表等应该以\l_或开头,具体取决于是本地的还是全局的。因此,我将其更改为。根据文档,流应该仅声明为全局的,因此我在命名流时使用了。\g_\solution_text_tl\l_solution_text_tl\g_

% !TEX TS-program = pdflatex
% !TEX encoding = UTF-8 Unicode
% arara: pdflatex
\pdfminorversion=7
% \listfiles
\documentclass{article}

\usepackage{l3regex}
\usepackage{environ}
\usepackage{marginnote}

\newcommand*\mymarks[1]{\marginnote{[#1]}}

\ExplSyntaxOn
\NewEnviron{solution}
 {
  \strip_marks:V \BODY
 }

\tl_new:N \l_solution_text_tl
\iow_new:N \g_solution_stream

\cs_new_protected:Npn \strip_marks:n #1
 {
  \tl_set:Nn \l_solution_text_tl { #1 }
  \l_solution_text_tl  % Inserts original text in the right place
  \regex_replace_all:nnN { \c{mymarks}\cB\{ [0-9]* \cE\} } {   } \l_solution_text_tl
  \regex_replace_all:nnN { \c{mymarks} [0-9] } {   } \l_solution_text_tl
%   \l_solution_text_tl <-- ***Regex done, how to write to file?***
  \iow_now:NV \g_solution_stream \l_solution_text_tl
 }
\AtBeginDocument{
  \iow_open:Nn \g_solution_stream { \jobname-soln.tex }
}
\AtEndDocument{
  \iow_close:N \g_solution_stream
}
\cs_generate_variant:Nn \strip_marks:n { V }
\cs_generate_variant:Nn \iow_now:Nn { NV }
\ExplSyntaxOff

\begin{document}
\begin{solution}
This line has a \emph{mark} at the end of it.\mymarks{10}
\end{solution}
\end{document}

编辑

您可以看到,通过在定义中添加\BODY以下内容,包含了换行符和\par空白行的空格:\show \BODY\mymarks

\NewEnviron{solution}
 {
   \show \BODY
  \strip_marks:V \BODY
 }

\BODY在将其传递给之前在控制台上显示其内容\strip_marks:V

> \BODY=macro:
->This line has a \emph {mark} at the end of it.\mymarks {10} \par This line fo
llows a paragraph break.\mymarks {90} That was a line break..
\env@solution@process ->\show \BODY 
                                    \strip_marks:V \BODY \env@ignore 
l.49 \end{solution}

其中的内容solution

\begin{solution}
This line has a \emph{mark} at the end of it.\mymarks{10}

This line follows a paragraph break.\mymarks{90}
That was a line break.
\end{solution}

相关内容