我想定义一个环境(碰巧在一个类文件中),其内容在编写时显示在屏幕上,但它们也会被修改(例如使用包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:
请注意,如果您的命令序列带有参数,则需要适当指定签名并给出参数:
\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}