\仅输入文件的一部分

\仅输入文件的一部分

我想将 .tex 文件的部分内容包含到另一个 .tex 文件中。我没有修改要包含的文件的选项。要包含的文件可能会发生变化,因此简单地复制和粘贴我需要的部分并不理想。

本质上,我想知道是否有东西可以像

\input[start-end]{file.tex}

文件中要包含的第一行和最后一行在start哪里?end

答案1

这是纯 TeX(好吧,e-TeX)的方法。主要思想是:要选择文件中的行范围,sed 是多余的,TeX 绰绰有余。作为奖励,不需要临时文件。

\documentclass[a4paper]{article}
\usepackage[ascii]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{lmodern}

\makeatletter
\newread\pin@file
\newcounter{pinlineno}
\newcommand\pin@accu{}
\newcommand\pin@ext{pintmp}
% inputs #3, selecting only lines #1 to #2 (inclusive)
\newcommand*\partialinput [3] {%
  \IfFileExists{#3}{%
    \openin\pin@file #3
    % skip lines 1 to #1 (exclusive)
    \setcounter{pinlineno}{1}
    \@whilenum\value{pinlineno}<#1 \do{%
      \read\pin@file to\pin@line
      \stepcounter{pinlineno}%
    }
    % prepare reading lines #1 to #2 inclusive
    \addtocounter{pinlineno}{-1}
    \let\pin@accu\empty
    \begingroup
    \endlinechar\newlinechar
    \@whilenum\value{pinlineno}<#2 \do{%
      % use safe catcodes provided by e-TeX's \readline
      \readline\pin@file to\pin@line
      \edef\pin@accu{\pin@accu\pin@line}%
      \stepcounter{pinlineno}%
    }
    \closein\pin@file
    \expandafter\endgroup
    \scantokens\expandafter{\pin@accu}%
  }{%
    \errmessage{File `#3' doesn't exist!}%
  }%
}
\makeatother

% for testing purpose
\begin{filecontents}{pitest}
5 You shouldn't see this.\par
6 Let the fun begin!
7 \iffalse
8 bla
9 \fi

11 New paragraph.
12 \verb*+\foo (two  spaces)~_$^+ bla
13 You shouldn't see this.\par
\end{filecontents}

\begin{document}

\partialinput{6}{12}{pitest} random text

\end{document}

我认为/希望这种方法是可靠的,这主要归功于 e-TeX 的\readline。请参阅随附的测试文件,了解可行的潜在边缘情况。

答案2

Manuel 发布了一个使用行号的答案;CTAN 上有一个最新包,可让您使用输入文件中的标签来完成此操作:捕捉标签之间的文件

一个例子是

\usepackage{catchfilebetweentags}
...
\ExecuteMetaData[file.tex]{tag}

外部文件的内容被“标签”包围:

%<*tag>
...
%</tag>

答案3

正如注释中所述,sed -ne 42,99p将把第 42–99 行(含)从其输入复制到其输出。这是假设您使用的是某种 unix(尽管我认为您也可以在 windows 上使用 sed)。您可以在脚本或 makefile 中执行此操作,将结果放在您包含的临时文件中。

或者,假设你使用的是 unix,你可以使用一些温和的 unix 魔法:假设你想要包含一部分的 TeX 文件名为foo.tex。然后你可以这样做

mkfifo foosnips.tex
while sed -ne 42,99p foo.tex > foosnips.tex || [ $? == 141 ]; do sleep 1; done &

(如果不是 (ba)sh,请根据您的 shell 进行修改)然后输入foosnips主 TeX 文件。每次对其进行 TeX 处理时,sed 命令都会提取请求的行。后台作业应该会一直运行,直到您重新启动计算机,但由于 fifo 的工作方式,它实际上不会执行任何操作,直到 fifo 被打开以供读取。当不再需要它时,或者如果您需要调整参数,请手动将其终止。

这样做也许不值得,除非foo.tex经常更改,或者摘录非常大而您不想将其保存为单独的文件。

(退出状态 141(128+13,其中 13 是 PIPE 信号的信号编号)的测试是为了确保如果您只读取 fifo 的部分输出,循环不会终止,就像 TeX 由于某些错误而退出时一样。并且需要睡眠以确保 fifo 接收端的进程有机会在新的 sed 进程启动之前关闭文件。)

答案4

这是完全没有经过测试的东西!

\newread\pin
\newcount\pcount
\def\partialinput[#1-#2]#3{%
    \openin\pin #3
    \global\pcount0
    \loop\ifnum\pcount<#1\relax
        \read\pin to\l
        \global\advance\pcount1
    \repeat
    \loop\ifnum\pcount<#2\relax
        \read\pin to\l\l
        \global\advance\pcount1
    \repeat
    \read\pin to\l\l
    \closein\pin
}

模数错误,定义了一个\partialinput应该按照您描述的方式工作的新宏。

实际上,数字行从 0 开始。请将其替换\global\pcount0\global\pcount1从 1 开始。

相关内容