file1
とfile2
の2つのファイルがあります。
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
注意してください:-一緒になっている行だけが出力の一部である必要があります。
grep
は複数行のパターンに関してはかなりばかげていますが、パターンとテキストの両方のすべての改行文字_\n
_を変換して、比較する前にNUL文字_\0
_に検索すると修正されます。出力の_\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)
は、_file1
_に等しいが、すべての改行文字がNUL文字に変換されたFIFO /名前付きパイプ/一時ファイルのようなオブジェクトを作成します。<(tr '\n' '\0' < file2)
も同じことをしますが、_file2
_の場合です。grep -f PATTERN_FILE INPUT_FILE
_は、_PATTERN_FILE
_の_INPUT_FILE
_からパターンを検索します。grep
の_-a
_フラグは、バイナリファイルでの照合を有効にします。これが必要なのは、そうしないと、_\0
_のような印刷できない文字を含むファイルがスキップされるためです。grep
の_-o
_フラグを使用すると、一致するシーケンスのみが出力され、見つかった行全体は出力されません。| tr '\0' '\n'
_は、左側のコマンドの出力からすべてのNUL文字を改行文字に変換します。以下は不器用ですが、GNU awk
で動作します。
awk -v RS="$(<file1)" '{print RT}' file2
純粋な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
これがもう少しエレガントな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に特に感謝します)
コストで述べたように、他のPerl
コマンドの代わりにPerl -0pe 's/\n(\n+$)?/\\n/g'
を使用して、_file1.txt
_の末尾の改行を回避できます。
grep -lir 'A B \n D C \n whatever' ./folder_to_search
結果は、テキストが完全に一致するすべてのファイルになります
出力をどのようにするかはよくわかりませんが、行指向ではない言語(特に両方のファイルをメモリに読み込むことができる場合)を使用するのは簡単です。これが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
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
を介したコマンドライン引数の処理は確かに単純です。 Finder
に渡す以外に、渡す2つのmemoryview
オブジェクトでTuple
の戻り値を使用して他の多くのことを行うことができます。 Finder
によって返されるイテレータによって生成される各SRE_Match
アイテムにはさまざまなメソッドがあり、そのサンプリングはprint
出力(span
、たとえば、各一致のバイト範囲を示します)。