web-dev-qa-db-ja.com

file2からの正確な行ブロック(file1のコンテンツ)をgrepします。

file1file2の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

注意してください:-一緒になっている行だけが出力の一部である必要があります。

9
sachin

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文字を改行文字に変換します。
11
Byte Commander

以下は不器用ですが、GNU awkで動作します。

awk -v RS="$(<file1)" '{print RT}' file2
6
Michael Vehrs

純粋な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
Costas

これがもう少しエレガントな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_の末尾の改行を回避できます。

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

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

1
meyerson

出力をどのようにするかはよくわかりませんが、行指向ではない言語(特に両方のファイルをメモリに読み込むことができる場合)を使用するのは簡単です。これが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
alexis

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、たとえば、各一致のバイト範囲を示します)。

0
Eirik Fuller