file2から行の正確なブロック(file1の内容)をgrep


9

2つのファイルがfile1ありfile2ます。

のサンプルコンテンツfile1は次のとおりです。

A B
C D
E F
G H

の内容file2は次のようなものです:

A B
few other lines
E F
few more other lines
A B
C D
E F
G H
few more other lines
G H

したがって、file1コンテンツのブロック全体file2のみを検索したいと考えています。つまり、出力には次の行のみが含まれます。

A B
C D
E F
G H

注意してください:-一緒に来る行のみが出力の一部になるはずです。


あなたの質問は聞き取れません。の正確な内容だけを印刷したい場合はfile1、を使用してくださいcat file1
ワイルドカード

@ワイルドカード彼は、file2にfile1とまったく同じ内容が含まれているかどうかを確認したいと考えています。本の中で特定の章を探すかのように考えてください
セルギー・コロディアズニー

「セットメンバー」は複数の行で構成されているため(最初は確認していません)、提案された重複した質問に対する承認済みの回答で処理される単一の行よりも少し複雑であるため、これを再度開くことにします。
クサラナンダ

1
これはセットについてではありません。これを重複としてマークしたい場合は、少なくとも複数行の正規表現に関する別の質問を見つけてください。
Michael Vehrs

回答:


11

grep複数行パターンに関してはかなり愚かですが\n、パターンとテキストの両方のすべての改行文字を\0比較して、それらを比較する前にNUL文字に検索することでこれを修正します。翻訳\0への出力バックに\n明らかにも必要とされています。

file1検索したいパターンが含まれていると仮定したコマンドはfile2次のとおりです。

grep -aof <(tr '\n' '\0' < file1) <(tr '\n' '\0' < file2) | tr '\0' '\n'

指定したファイルの出力例:

A B
C D
E F
G H

説明:

  • <(tr '\n' '\0' < file1)に等しいFIFO /名前付きパイプ/一時ファイルのようなオブジェクトを作成しfile1ますが、改行文字はすべてNUL文字に変換されます。
  • <(tr '\n' '\0' < file2)同じことはありませんが、ためfile2
  • grep -f PATTERN_FILE INPUT_FILEでパターンを検索PATTERN_FILEINPUT_FILEます。
  • -aフラグは、grepバイナリファイルのマッチングを可能にします。そうしないと、などの印刷できない文字を含むファイルがスキップされるため、これが必要です\0
  • -oフラグはgrep、一致するシーケンスのみを印刷し、見つかった行全体を印刷しないようにします。
  • | tr '\0' '\n' すべてのNUL文字を左側のコマンドの出力から改行文字に変換します。


3

純粋なbashでの楽しみのために

mapfile -t <file1
while read line ; do
    [ "$line" = "${MAPFILE[i++]}" ] || { ["$line" = "$MAPFILE" ] && i=1 || i=0; }
    [ $i -eq ${#MAPFILE[*]} ] && { printf "%s\n" "${MAPFILE[@]}"; i=0; }
done <file2

3

これがもう少しエレガントですgrep+ perl

$ grep -Pzo "$(perl -pe 's/\n/\\n/g' file1.txt )"  file2.txt                    
A B
C D
E F
G H

ただし、大きな問題が1つあります。に末尾の改行がある場合file1、パターンは正しくありませんA B\nC D\nE F\nG H\n\n。つまり、です。

(perlパーツを提供してくれた@terdonに感謝)

Costasが述べたようperl -0pe 's/\n(\n+$)?/\\n/g' に、他のperlコマンドの代わりに使用して、file1.txt


1
後続の改行があり、それがOPでない場合は、OPを検索しますperl -0pe 's/\n(\n+$)?/\\n/g'。正規表現なし-0g修飾子は余分です。
Costas

1

出力をどのようにしたいのかよくわかりませんが、(特に両方のファイルをメモリに読み込むことができる場合は)行指向だけではない言語を使用するのは簡単です。以下は、一致の数を通知するpythonスクリプトです。

import sys
find = open(sys.argv[1]).read()
hay = open(sys.argv[2]).read()
print("The text occurs", hay.count(find), "times")

file1何回でも印刷したいですか?最後の行をこれで置き換えます:

print(find * hay.count(find))

本当に必要な場合は、すべてをコマンドライン呼び出しまたはエイリアスにパックできます。

python -c 'import sys; print("The text occurs", open(sys.argv[2]).read().count(open(sys.argv[1]).read()), "times")' file1 file2

1
grep -lir 'A B \n D C \n whatever' ./folder_to_search

結果は、完全にテキストが一致するすべてのファイルになります


0

これはpythonを使用した別のアプローチです(でテストされpython3 3.5.2、からの不満はありませんpylint3 1.5.6)。

""" Locate entire file contents contiguous in other file """

import sys
import re
from mmap import mmap, PROT_READ

def memmap(name):
    """ Return memoryview of readonly mmap """
    with open(name, 'rb') as file:
        return memoryview(mmap(file.fileno(), 0, access=PROT_READ))

def finder(needle, haystack):
    """ Return iterator """
    return re.compile(re.escape(needle)).finditer(haystack)

print(tuple(finder(*(memmap(name) for name in sys.argv[1:3]))))

を介したコマンドライン引数の処理は、sys.argv明らかに単純化されています。に渡す以外にも、渡すfinder2つのmemoryviewオブジェクトのの戻り値を使用して他の多くのことを行うことができますtupleSRE_Matchによって返されたイテレータによって生成された各項目にはfinderさまざまなメソッドがあり、そのサンプリングがprint出力に要約されます(spanたとえば、は各一致のバイト範囲を示します)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.