文本文件中字符串的参考行号

文本文件中字符串的参考行号

我想引用非 TeX 文本文件中包含固定字符串的一行。我只想获取其行号。我需要对同一个文件执行多次此操作,因此如果有解决方案不必在每次使用时读取该文件,那就太好了。

我发现了另一个与列表有关的 SE 问题,它几乎可以满足我的要求。它使用转义符并将链接嵌入到源文件中。我几乎可以使用它,但有两点我不喜欢它。1. 它要求我编辑文本文件并添加转义符和一些 TeX 代码。我真的不想这样做。2. 它似乎在最终结果(pdf 等)中包含列表,而我不需要或不想要它。

答案1

我将提出两种解决方案:简单和更复杂。

如果文件纯粹由文本材料组成,那么这种更简单的方法应该可行。我使用readarray将文件导入到添加了行分隔符的文件中\def\\然后我使用嵌套\listofitems解析来查找包含定义的行\matchstring。结果是一个宏\lineindex,其中包含文件中匹配字符串的(逗号分隔)行号。A-1表示未找到字符串匹配。

如果文件和搜索词是简单文本,不包含特殊字符,则使用简单代码。因此,此版本将遇到 4 种会破坏文件读取的情况,因为它是使用默认 LaTeX 代码读取的。这 4 种情况是:

  1. #

  2. %将作为注释并遮挡输入行的剩余部分。

  3. \...形成未定义的宏名。

  4. 不平衡{}

即使使用平衡括号,也存在其他限制:在括号组内不会找到搜索项;如果括号组跨越输入文件的多行,则从 到 的行将{}视为单行输入(即,该组将被强制视为在一行上)。

因此,第一种方法仅适用于简单的文本搜索。

妇女权利委员会:

\documentclass{article}
\usepackage{readarray,listofitems,pgffor}
\begin{filecontents*}[overwrite]{mydata.txt}
There came from Nantucket a lemur,
who texted his doctor in beamer.
  a misplaced italic
  made his problem seem phallic
but in fact he had bruised just his femur.
\end{filecontents*}
% THE STRING OF INTEREST IS PLACED IN \matchstring
% WHICH IS THE ARGUMENT FOR \prep
\def\setmatchstring#1{\def\matchstring{#1}}
\def\searchformatch#1{%
  \readarraysepchar{\\}
  \expandafter\setsepchar\expandafter{\expandafter
    \\\expandafter/\matchstring}
  \readdef{#1}\mydatafile 
  \def\lineindex{}%
  \readlist\mydata{\mydatafile}%
  \foreachitem\z\in\mydata[]{%
    \ifnum\listlen\mydata[\zcnt]>1\relax
      \if\relax\lineindex\relax
        \xdef\lineindex{\zcnt}\else
        \xdef\lineindex{\lineindex, \zcnt}%
      \fi
    \fi
  }%
  \if\relax\lineindex\relax\gdef\lineindex{-1}\fi
}
\begin{document}
\setmatchstring{misplaced italic}
\searchformatch{mydata.txt}

The line containing the ``\matchstring'' is \lineindex.
\end{document}

在此处输入图片描述

对于更复杂的解决方案,所有四个限制都已通过 catcode 技巧克服。\setmatchstring此修订版中的宏不使用大括号输入,而是遵循类似于的方法\verb,其中用户指定不属于搜索字符串的分隔符:例如,使用@分隔符

\setmatchstring @f}f}#@

将搜索字符串设置为f}f}#。以下是 MWE:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{readarray,listofitems,pgffor}
\begin{filecontents*}[overwrite]{mydata.txt}
Account: Framistat{$#@}
Password: \gY^&$%\{x#
Encrypted Hash Code: ef}f}#$_+{
Expiration: \today
\end{filecontents*}

% THE STRING OF INTEREST IS PLACED IN \matchstring
\def\setmatchstring#1{%
  \begingroup
  \def~##1#1{\gdef\matchstring{##1}\endgroup
    \catcode`\\=0 
    \catcode`\{=1 
    \catcode`\}=2 
    \catcode`\%=14
    \catcode`\#=6
  }%
  \catcode`\#=12
  \catcode`\%=12
  \catcode`\\=12 
  \catcode`\{=12 
  \catcode`\}=12 
  ~%
}
\def\searchformatch#1{%
  \readarraysepchar{\SFLINEEND}%
  \expandafter\setsepchar\expandafter{\expandafter
    \SFLINEEND\expandafter/\matchstring}%
  \def\tmpA{%
    \catcode`\#=12
    \catcode`\%=12 
    \catcode`\\=12 
    \catcode`\{=12 
    \catcode`\}=12 }%
  \def\tmpB{%
    \readdef{#1}\mydatafile
    \catcode`\\=0 
    \catcode`\}=2 
    \catcode`\{=1 
    \catcode`\%=14
    \catcode`\#=6 }%
  \expandafter
    \tmpA\tmpB
  \def\lineindex{}%
  \readlist\mydata{\mydatafile}%
  \foreachitem\z\in\mydata[]{%
    \ifnum\listlen\mydata[\zcnt]>1\relax
      \if\relax\lineindex\relax
        \xdef\lineindex{\zcnt}\else
        \xdef\lineindex{\lineindex, \zcnt}%
      \fi
    \fi
  }%
  \if\relax\lineindex\relax\gdef\lineindex{-1}\fi
}
\begin{document}
\setmatchstring @f}f}#@
\searchformatch{mydata.txt}
The line index containing ``\matchstring'' is \lineindex.

\setmatchstring !%\{x#!
\searchformatch{mydata.txt}
The line index containing ``\matchstring'' is \lineindex.
\end{document}

在此处输入图片描述

相关内容