如何替换 TeX' \write 命令写入的文件中一行

如何替换 TeX' \write 命令写入的文件中一行

我尝试使用 TeX\immediate\write命令在外部文件中写入一些内容。

\documentclass{scrartcl}

\begin{document}

\newwrite\tempfile
\immediate\openout\tempfile=lists.tex
\immediate\write\tempfile{line1}
\immediate\write\tempfile{}
\immediate\write\tempfile{line2}
\immediate\closeout\tempfile

\input{lists}

\end{document}

有没有方法可以在代码的后面替换这个 lists.tex 中的一行(例如“line2”)?

答案1

TeX 不允许您以附加或覆盖权限打开文件:只存在读取和写入。您可以通过读取文件、替换要替换的内容,然后重写来伪造该行为。

以下是andexpl3的实现,它将替换给定的一个或所有出现的\replacelineonce\replacelineall细绳在文件中。语法为:

\replacelineonce{<file>}{<search string>}{<replacement>}
  {<true code>}{<false code>}

代码将逐行读取<file>字符串(像\{等字符没有其特殊含义),查找<search string>(仅匹配整行),如果找到,将替换为<replacement>。替换后,文件将使用更改后的内容重写。如果进行了任何替换,则<true code>在最后执行 ,否则<false code>执行 。如果输入文件不存在,则会引发错误并<false code>执行 。\replacelineonce将在第一次替换后停止,而\replacelineall将替换所有出现的内容。

\documentclass{article}

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \replacelineonce { m m m m m }
  { \mountain_replace_once:nnnTF {#1} {#2} {#3} {#4} {#5} }
\NewDocumentCommand \replacelineall { m m m m m }
  { \mountain_replace_all:nnnTF {#1} {#2} {#3} {#4} {#5} }
\tl_new:N \l__mountain_tmpa_tl
\tl_new:N \l__mountain_file_seq
\bool_new:N \l__mountain_replaced_bool
\ior_new:N \l__mountain_replace_ior
\iow_new:N \l__mountain_replace_iow
\prg_new_protected_conditional:Npnn \mountain_replace_once:nnn #1 #2 #3 { T, F, TF }
  { \__mountain_replace_aux:Nnnn \c_false_bool {#1} {#2} {#3} }
\prg_new_protected_conditional:Npnn \mountain_replace_all:nnn #1 #2 #3 { T, F, TF }
  { \__mountain_replace_aux:Nnnn \c_true_bool {#1} {#2} {#3} }
\cs_new_protected:Npn \__mountain_replace_aux:Nnnn #1 #2 #3 #4
  {
    \ior_open:NnTF \l__mountain_replace_ior {#2}
      { \__mountain_replace_line:Nnnn #1 {#3} {#4} {#2} }
      {
        \msg_error:nnn { mountain } { file-not-found } {#2}
        \prg_return_false:
      }
  }
\cs_new_protected:Npn \__mountain_replace_line:Nnnn #1 #2 #3 #4
  {
    \seq_clear:N \l__mountain_file_seq
    \bool_set_false:N \l__mountain_replaced_bool
    \ior_str_map_inline:Nn \l__mountain_replace_ior
      {
        \str_if_eq:nnTF {##1} {#2}
          {
            \bool_set_true:N \l__mountain_replaced_bool
            \seq_put_right:Nn \l__mountain_file_seq {#3}
            \bool_if:NF #1
              { \ior_map_break:n { \__mountain_replace_skip: } }
          }
          { \seq_put_right:Nn \l__mountain_file_seq {##1} }
      }
    \__mountain_replace_end:n {#4}
  }
\cs_new_protected:Npn \__mountain_replace_skip:
  {
    \ior_str_map_inline:Nn \l__mountain_replace_ior
      { \seq_put_right:Nn \l__mountain_file_seq {##1} }
  }
\cs_new_protected:Npn \__mountain_replace_end:n #1
  {
    \ior_close:N \l__mountain_replace_ior
    \iow_open:Nn \l__mountain_replace_iow {#1}
    \seq_map_inline:Nn \l__mountain_file_seq
      { \iow_now:Nn \l__mountain_replace_iow {##1} }
    \iow_close:N \l__mountain_replace_iow
    \bool_if:NTF \l__mountain_replaced_bool
      { \prg_return_true: }
      { \prg_return_false: }
  }
\msg_new:nnn { mountain } { file-not-found }
  { File~`#1'~not~found. }
\ExplSyntaxOff

\begin{document}

\newwrite\tempfile
\immediate\openout\tempfile=lists.tex
\immediate\write\tempfile{line1}
\immediate\write\tempfile{}
\immediate\write\tempfile{line2}
\immediate\write\tempfile{}
\immediate\write\tempfile{line2}
\immediate\write\tempfile{}
\immediate\write\tempfile{line2}
\immediate\closeout\tempfile

\replacelineonce{lists.tex}{line2}{line replaced}
  {Replaced once:}
  {Nothing replaced:}

\input{lists}
\bigskip

\replacelineall{lists.tex}{line2}{line replaced}
  {Replaced all:}
  {Nothing replaced:}

\input{lists}
\bigskip

\replacelineonce{lists.tex}{line2}{line replaced}
  {Replaced once:}
  {Nothing replaced:}

\input{lists}
\bigskip

\end{document}

答案2

如果需要进行更改,最好将其保存在 TeX 中。这会生成一个列表宏而不是写入文件,然后排版内容,写入一个文件,然后应用更改并再次排版,然后写入第二个文件。

因此排版输出是

在此处输入图片描述

lists.tex写为

line1

line2

lists2.tex写为

line1

line 2 changed

来自 tex 文件:

\documentclass{scrartcl}

\newwrite\tempfile


\def\foo{}
\def\addline#1#2{\edef#1{\unexpanded\expandafter{#1\\{#2}}}}
\begin{document}



\addline\foo{line1}
\addline\foo{}
\addline\foo{line2}


{\def\\#1{#1 }\foo}% typeset it, was \input
{\def\\#1{#1^^J}
\immediate\openout\tempfile=lists.tex
\immediate\write\tempfile{\foo}
} % write first version
\immediate\closeout\tempfile



\def\\#1{%
\ifnum\pdfstrcmp{#1}{line2}=0
\unexpanded{\\{line 2 changed}}%
\else
\unexpanded{\\{#1}}%
\fi
}
\edef\foo{\foo} % apply the change

{\def\\#1{#1 }\foo}% typeset new version
{\def\\#1{#1^^J}
\immediate\openout\tempfile=lists2.tex
\immediate\write\tempfile{\foo}
} % write new version
\immediate\closeout\tempfile




\end{document}

相关内容