如何查找其他行上两个字符串之间出现的字符串

如何查找其他行上两个字符串之间出现的字符串

我如何搜索前面有另一个字符串的某个字符串(在大多数情况下是几行),后面跟着另一个字符串,即包含在某个环境中?

\begin{quote}
%several lines of text
\footnote{%
%probably a few more lines of footnote content
}
%several lines of further text
\end{quote}

因此,我正在搜索\footnote{引用环境中包含的脚注(以 开头)(以 开头\begin{quote},以 结尾end{quote},在大多数情况下跨越几行)。实际上,实际上我应该搜索脚注中包含的另一个环境,这些环境发生在引用环境中,从而添加第二层条件,但可能一旦我理解了简化的示例,我就可以弄清楚我的现实世界问题。我搜索的实际环境在包含大约 20 个文件的目录中出现了大约 150 次.tex,这些文件构成了一本大约 500 页的书的源代码,该书预计将在几天内印刷,并且这种特定的组合会产生不良效果,很多时候,如果不仔细看,就会被忽视。

作为搜索的输出,我想获取匹配发生的文件名(我可能会搜索*tex,不过,如果这太复杂,我也可以使用 bash for 循环)及其行号。

人们还必须记住这一点

\begin{quote}
%something
\end{quote}
%something
\footnote{%
%something
}
%something
\begin{quote}
%something
\end{quote}

某件事会发生很多次,但这将是误报。

答案1

你不能用 来做到这一点grep,你需要一些更有能力的东西,比如awkperl。这是在 perl 中执行此操作的一个非常简单的示例:

$ cat find-fn-in-quote.pl 
#!/usr/bin/perl

while(<>) {
  # strip comments so that we ignore commented-out quotes & footnotes.
  s/%[^%].*//;

  # detect beginning and end of quotes
  if (m/\Qbegin{quote}\E/) { $qt = 1; $ql = $.};
  if (m/\Qend{quote}\E/)   { $qt = 0 };

  if (eof) {
    # reset line-counter ($.) after every input file
    close(ARGV);

    # reset $qt to zero, in case of unbalanced begin/end{quote}
    $qt = 0;
  };

  # skip to next input line if we're not inside a quote.
  next unless ($qt);

  if (m/\\footnote\{/) {
   print "$ARGV: found footnote beginning on line $. inside quote beginning on line $ql\n";
   # For terse output, comment out or delete the print statement above
   # and un-comment one of these:
   #printf "%s:fn=%i:q=%i\n", $ARGV, $., $ql;
   #printf "%s:%i:%i\n", $ARGV, $., $ql;
  };

};

注意:此脚本无法正确处理嵌套begin{quote}。我怀疑这会成为一个问题,因为它不太可能在人为的示例之外发生。它还假设引用完全存在于一个文件中 - 事实上,脚本故意强制执行这一点,以确保一个输入文件中的错误(即缺少end{quote})不会影响后续文件。

我创建了 3 个文本文件来测试它。 input1.txt包含您的第一个示例输入。 input2.txt包含您的第二个示例输入以及您不想匹配的误报。 input3.txt包含 input2.txt 后跟 input1.txt (即cat input2.txt input1.txt > input3.txt)。在这些输入文件上运行脚本会产生以下输出:

$ ./find-fn-in-quote.pl *.txt
input1.txt: found footnote beginning on line 3 inside quote beginning on line 1
input3.txt: found footnote beginning on line 14 inside quote beginning on line 12

答案2

awk的一个版本

awk 'FNR==1{looking=0; print  FILENAME}
  $0~/begin{quote}/{looking=1;next}
  $0~/end{quote}/{looking=0;next}
  looking&&$0~/footnote{/{print FNR, $0}' *.tex

只需在报价开始时开始“查看”,在报价结束时停止“查看”。

就像 @cas 示例一样,它会在每次打开文件时重置。

如果您要在脚注中查找另一个环境,那么事情会变得更加棘手,因为您需要开始}\footnote不同的线路上寻找平衡,这是一种不同的动物。

答案3

GNU awk:

awk '
/^\\end{quote}$/ && fire        {report = report OFS str}
/^\\end{quote}$/                {block=cont=fire=0; str=""}
/^\\begin{quote}$/              {block=1}
block && /^\\footnote{%$/       {cont=1; str=FNR; next}
block && cont && /}/            {fire=1;cont=0}
ENDFILE                         {if(report)print FILENAME report; report = ""}
' *.tex

输出格式:

filename line_number line_number ...

每个文件的所有匹配行号都输出在一行中。不匹配的文件名不会显示。

相关内容