異なる行の2つの文字列の間に現れる文字列を見つける方法

異なる行の2つの文字列の間に現れる文字列を見つける方法

他の文字列(ほとんどの場合数行)の前にあり、他の文字列が続く(たとえば、特定の環境に含まれる)特定の文字列を検索するにはどうすればよいですか。

\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}(で始まる)を検索しています。実際には、参照された環境内で発生する脚注に含まれる他の環境を検索して2番目の条件レイヤーを追加する必要がありますが、おそらく単純化された例を理解したら、実際の質問を理解することができます。私が検索した実際の環境は、数日.tex以内に印刷されると予想される約500ページの本のソースコードを構成する約20個のファイルを含むディレクトリで約150回検索されています。インポートすることができ、何度も注意深く見ていないと、目立たなくなります。

*tex検索結果で一致が発生したファイル名(おそらく検索しますが、複雑すぎる場合はbash forループを使用する可能性があります)とその行番号を取得したいと思います。

人々もこれを覚えておくべきです

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

何かが何度も起こりますが、これは偽の肯定です。

答え1

これを行うために使用することはできません。またgrepはなどのより強力な機能が必要です。 Perlでこれを行う非常に簡単な例は次のとおりです。awkperl

$ 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}これを強制し、1つの入力ファイルのエラー(例:不在)が後続のファイルに影響を与えないようにします。

テスト用に3つのテキストファイルを作成しました。 input1.txt最初の入力例が含まれています。 input2.txt2番目の入力例と一致させたくない偽の肯定を含めてください。 input3.txtinput2.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 ...

各ファイルごとに一致する行番号がすべて1行に出力されます。一致しないファイル名は表示されません。

関連情報