Mam dwa pliki file1
i file2
.
Przykładowa zawartość file1
to:
A B
C D
E F
G H
a treść file2
jest jak:
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
Chcę więc przeszukać tylko cały blok file1
treści file2
. Oznacza to, że dane wyjściowe powinny zawierać tylko następujące wiersze:
A B
C D
E F
G H
należy pamiętać, że: - tylko linie, które się zbliżają, powinny stanowić część wyniku.
shell-script
text-processing
awk
sed
sachin
źródło
źródło
file1
i nic więcej, po prostu użyjcat file1
.Odpowiedzi:
grep
jest dość głupie, jeśli chodzi o wzory wielowierszowe, ale tłumaczenie wszystkich znaków nowego wiersza\n
zarówno wzorca, jak i tekstu w celu wyszukania znaków NUL\0
przed ich porównaniem naprawia to. Oczywiście konieczne jest także przetłumaczenie\0
danych wyjściowych na\n
.Oto twoje polecenie, przy założeniu, że
file1
zawiera wzorzec, który chcesz wyszukaćfile2
:Przykładowe dane wyjściowe dla podanych plików:
Wyjaśnienie:
<(tr '\n' '\0' < file1)
tworzy FIFO / nazwany potok / tymczasowy obiekt podobny do pliku, który jest równyfile1
, ale z wszystkimi znakami nowej linii przetłumaczonymi na znaki NUL.<(tr '\n' '\0' < file2)
robi to samo, ale dlafile2
.grep -f PATTERN_FILE INPUT_FILE
wyszukuje wzorce odPATTERN_FILE
wINPUT_FILE
.-a
Flagagrep
umożliwia dopasowanie do plików binarnych. Jest to potrzebne, ponieważ w przeciwnym razie pomija pliki zawierające znaki niedrukowalne, takie jak\0
.-o
Flagagrep
czyni go wydrukować tylko sekwencję dopasowanie, a nie całej linii, gdzie został znaleziony.| tr '\0' '\n'
tłumaczy wszystkie znaki NUL z danych wyjściowych polecenia po lewej stronie z powrotem na znaki nowego wiersza.źródło
Następujące jest niezdarne, ale działa z GNU
awk
:źródło
Tylko dla zabawy w czystym bashu
źródło
Oto nieco bardziej elegancki
grep
+perl
:Jest jednak jeden wielki haczyk. Jeśli istnieje w nowej linii spływu
file1
, wzór nie będzie poprawna, innymi słowy:A B\nC D\nE F\nG H\n\n
.(Specjalne podziękowania @terdon za udostępnienie części perla)
Jak zauważono, costas można użyć
perl -0pe 's/\n(\n+$)?/\\n/g'
zamiast drugiegoperl
polecenia, aby uniknąć końcowego znaku nowej linii wfile1.txt
źródło
perl -0pe 's/\n(\n+$)?/\\n/g'
. Bez-0
tejg
regex modyfikatora jest extra.Nie jestem do końca pewien, jaki ma być wynik, ale łatwo to zrobić w językach, które nie są wyłącznie zorientowane liniowo (szczególnie jeśli oba pliki można odczytać do pamięci). Oto skrypt Pythona, który powie ci, ile jest dopasowań.
Chcesz wydrukować
file1
tyle razy, ile pasuje? Zastąp ostatni wiersz tym:Możesz spakować wszystko do linii poleceń lub aliasu, jeśli naprawdę chcesz:
źródło
wynikiem będą wszystkie pliki z dokładnym dopasowaniem tekstu
źródło
Oto inne podejście z użyciem Pythona (przetestowane z
python3 3.5.2
, bez żadnych skarg odpylint3 1.5.6
):Obsługa argumentów wiersza poleceń za pośrednictwem
sys.argv
jest oczywiście uproszczona. Mógłbyś robić wiele innych rzeczy z wartością zwracanąfinder
na dwóchmemoryview
obiektach, które przekazujesz, poza tym przekazywać je dotuple
. KażdySRE_Match
element zwrócony przez iterator zwracany przezfinder
ma różne metody, których próbkowanie jest podsumowane w danychprint
wyjściowych (span
na przykład informuje o zakresie bajtów każdego dopasowania).źródło