7.7 複数行にまたがるテキストの検索
この節では、NとDコマンドを使って、複数行にまたがる連続した単語を検索します。複数行を扱う手法:D,G,H,N,Pによる複数行の処理を参照してください。
ここでは、文書内で同じ単語が続けて2回現れる箇所を探す例を扱います。
1行の中で重複する単語は、GNU grepで簡単に見つけられます。GNU sedでも同様です。
$ cat two-cities-dup1.txt
It was the best of times,
it was the worst of times,
it was the the age of wisdom,
it was the age of foolishness,
$ grep -E '\b(\w+)\s+\1\b' two-cities-dup1.txt
it was the the age of wisdom,
$ grep -n -E '\b(\w+)\s+\1\b' two-cities-dup1.txt
3:it was the the age of wisdom,
$ sed -En '/\b(\w+)\s+\1\b/p' two-cities-dup1.txt
it was the the age of wisdom,
$ sed -En '/\b(\w+)\s+\1\b/{=;p}' two-cities-dup1.txt
3
it was the the age of wisdom,
- 正規表現「\b\w+\s+」は、単語境界(「\b」)、1文字以上の単語構成文字(「\w+」)、空白(「\s+」)の順に並ぶ箇所を検索します。正規表現の拡張を参照してください。
- 「(\w+)」を丸括弧で囲むと、部分式になります。正規表現パターン「(PATTERN)\s+\1」は、丸括弧内の部分式の後に、空白を挟んで後方参照が続く形を定義します。マッチした場合は、PATTERNが連続して2回現れたことを意味します。後方参照と部分式を参照してください。
- 両端にある単語境界の式(「\b」)によって、単語の一部にはマッチしなくなります(たとえば、「the then」へのマッチは意図したものではありません)。
- -Eオプションは拡張正規表現の構文を有効にし、丸括弧の前にバックスラッシュを付ける必要をなくします。拡張正規表現の構文の概要を参照してください。
重複する単語が2行にまたがる場合、上の正規表現では見つかりません。grepとsedは1行ずつ処理するためです。
NとDコマンドを使えば、sedで複数行に正規表現を適用できます(つまり、複数行をパターンスペースに格納し、それに対して正規表現を適用します)。
$ cat two-cities-dup2.txt
It was the best of times, it was the
worst of times, it was the
the age of wisdom,
it was the age of foolishness,
$ sed -En '{N; /\b(\w+)\s+\1\b/{=;p} ; D}' two-cities-dup2.txt
3
worst of times, it was the
the age of wisdom,
Nコマンドは、次の行をパターンスペースに追加します(これにより、各サイクルで連続する2行がパターンスペースに含まれます)。- この正規表現では、単語の区切りに「\s+」を使います。これはスペースにも改行にもマッチします。
- 正規表現にマッチしたら、
pでパターンスペース全体を出力します。-nオプションがあるため、既定では行は出力されません。 Dは、パターンスペースから最初の行を削除し(最初の改行までを取り除き)、次のサイクルに備えます。
tr -sとuniqを使う別の解法については、GNU coreutilsマニュアルのhttps://gnu.org/s/coreutils/manual/html_node/Squeezing-and-deleting.htmlを参照してください。