2014-11-05 12 views
6

Mam diff, który zasadniczo równa się dodatkowe unikalne linie lub linie, które zostały przeniesione w pliku, a tym samym ich numery linii zostały zmienione. Aby ustalić, co jest naprawdę nowy dodatek, uruchomić ten mały perl fragment, aby oddzielić linie „rozwiązane” z „nierozwiązanych” linii:grep nie działa zbyt dobrze na dużych plikach, czy jest alternatywa?

perl -n -e' 
    /^\-([^\-].*?)\([^,\(]+,\d+,\d+\).*$/ && do { print STDOUT "$1\n"; next; }; 
    /^\+([^\+].*?)\([^,\(]+,\d+,\d+\).*$/ && do { print STDERR "$1\n"; next; }; 
' "$delta" 1>resolved 2>unresolved 

Jest to dość szybkie w rzeczywistości, a nie praca, oddzielając 6000 + linia zmienia się w dwa pliki o rozmiarze ponad 3000, usuwając wszelkie odniesienia do numerów linii i jednolitej dekoracji diff. Następnie przychodzi polecenie grep, który wydaje się działać na 100% CPU przez prawie 9 minut (Real):

grep -v -f resolved unresolved 

ta jest zasadniczo usunięcie wszystkich rozwiązane wiersze z pliku nierozwiązany. Wyjście po 9 minutach jest przypadkowo 9 liniami wyjścia - unikalnymi dodatkami lub nierozwiązanymi liniami.

Po pierwsze, kiedy używałem grep w przeszłości, było w tym całkiem nieźle, więc dlaczego w tym przypadku jest wyjątkowo wolny i głodny procesor?

Po drugie, czy istnieje skuteczniejszy alternatywny sposób usuwania linii z jednego pliku zawartego w innym?

+0

Okay, myślę, że odpowiedziałem trochę na moje własne pytanie liczbami. Grep analizuje 3000 wierszy pliku, potencjalnie 3000 razy, więc być może odpowiada to analizie pliku o wartości 9 000 000 wierszy. Ale to wciąż nie jest takie ogromne. To prawie tak, jakby grep zajmuje 60 sekund, aby przeanalizować 1 000 000 linii. – Craig

+0

Zauważ, że '. * $' Jest bezużyteczne – ikegami

+0

Oczywiście, ale pomyślałem, że może być trochę samotny bez $. :-) – Craig

Odpowiedz

5

Grep prawdopodobnie analizuje ten plik w całości dla każdego dopasowania, które zostało mu powiedziane. Możesz wypróbować "fgrep", jeśli istnieje w twoim systemie, lub grep -F jeśli nie, to zmusza grep do użycia algorytmu dopasowywania ciągów Aho-Corasick (http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm), który próbuje dopasować wszystkie ciągi jednocześnie, tylko wymagający jednego przeglądanie pliku.

+0

Wow, co za różnica. Oto czas rozwiązania fgrep: prawdziwe 0m0,049s, użytkownik 0m0.041s, sys 0m0.009s – Craig

8

Jeśli linie mają być dopasowane do obu plików mają być dokładne wyniki, można użyć sort i uniq aby wykonać zadanie:

cat resolved resolved unresolved | sort | uniq -u 

jedynym nie-zduplikowane wiersze w rurociągu powyżej woli be linie w nierozwiązane, które nie są w rozwiązane. Zauważ, że ważne jest, aby w komendzie cat dwukrotnie podać rozwiązane: w przeciwnym razie uniq wybierze również linie unikalne dla tego pliku. Zakłada się, że nierozwiązane rozwiązane nie mają zduplikowanych linii. Ale to dość łatwe do czynienia z: po prostu porządek i uniq nich pierwszy

sort resolved | uniq > resolved.uniq 
sort unresolved | uniq > unresolved.uniq 

Również znalazłem fgrep znacznie szybciej, jeśli staram się dopasować stałe ciągi, tak, że może być alternatywą.

+0

Rozwiązanie "Kot rozwiązany rozwiązany nierozstrzygnięty" zadziałało w ciągu 1 sekundy. Podaję również rozwiązanie fgrep. – Craig

+0

fajnie! Odmiana tego problemu jest czymś, o co czasem pytam w wywiadach. Zawsze interesujące, aby zobaczyć rzeczy, które ludzie wymyślają. – RS239

+0

Rozwiązanie fgrep wydaje się nieco szybsze, ale marginalnie. Oto czas dla tego rozwiązania: prawdziwe 0m0,220s, użytkownik 0m0,212s, sys \t 0m0.004s – Craig

Powiązane problemy