Параметры -A
и -R
принимают список, разделенный запятыми.
например.
wget -r -R -l1 --no-parent -A ".dat,.haa,.hea-,.hea--,.xws,.atr,.atr-" https://www.physionet.org/physiobank/database/nsrdb/
На странице руководства
-A acclist --accept acclist
-R rejlist --reject rejlist
Укажите разделенные запятыми списки суффиксов или шаблонов имен файлов для принятия или отклонения. Обратите внимание, что если какой-либо из подстановочных знаков , *,?, [Или] появляется в элементе acclist или rejlist, он будет рассматриваться как шаблон, а не суффикс.
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' создает FIFO / именованный канал / временный файловый объект, который равен file1
, но все символы новой строки переведены в символы NUL.
<(tr '\ n' '\ 0' делает то же самое, но для file2
.
grep -f PATTERN_FILE INPUT_FILE
ищет шаблоны из PATTERN_FILE
в INPUT_FILE
. -a
в grep
включает сопоставление двоичных файлов. Это необходимо, потому что в противном случае будут пропущены файлы, содержащие непечатаемые символы, такие как \ 0
. -o
команды grep
заставляет выводить только соответствующую последовательность, а не всю строку, в которой она была найдена. | tr '\ 0' '\ n'
переводит все символы NUL из вывода команды слева обратно в символы новой строки. Вот более элегантный вариант grep
+ perl
:
$ grep -Pzo "$(perl -pe 's/\n/\\n/g' file1.txt )" file2.txt
A B
C D
E F
G H
Однако есть одна большая загвоздка. Если в file1
есть завершающий символ новой строки, шаблон будет неправильным, другими словами: A B \ nC D \ nE F \ nG H \ n \ n
.
(Особая благодарность @terdon за предоставление части perl)
Как заметил Костас, можно использовать perl -0pe 's / \ n (\ n + $)? / \\ n / g'
вместо другой команды perl
, чтобы избежать завершающей новой строки в file1.txt
grep -lir 'A B \n D C \n whatever' ./folder_to_search
результатом будут все файлы с точным соответствием текста
Вот другой подход с использованием 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
на двух объектах memoryview
, которые вы передаете, кроме передачи его в tuple
. Каждый элемент SRE_Match
, выдаваемый итератором, возвращаемым finder
, имеет множество методов, выборка которых обобщена в выводе print
(в span
, например, указывается диапазон байт каждого совпадения).
Я не слишком уверен, каким вы хотите, чтобы выходные данные были, но это легко сделать с языками, которые не ориентированы исключительно на строку (особенно если оба файла могут быть прочитаны в памяти). Вот скрипт 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
Просто для удовольствия в чистом 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
Следующее неуклюже, но работает с GNU awk
:
awk -v RS="$(<file1)" '{print RT}' file2