Czy jest jakieś narzędzie, które może uzyskać linie, które zawiera plik A, ale plik B nie? Mógłbym napisać prosty skrypt z np. Perlem, ale jeśli coś takiego już istnieje, od tej pory oszczędzę czas.
command-line
stokrotka
źródło
źródło
Odpowiedzi:
Tak. Za pomocą standardowego
grep
narzędzia do wyszukiwania plików w poszukiwaniu ciągów tekstowych można odjąć wszystkie wiersze jednego pliku od drugiego.Działa to poprzez użycie każdej linii w pliku B jako wzorca (
-f fileB
) i traktowanie go jako zwykłego ciągu pasującego do siebie (nie zwykłego wyrażenia regularnego) (-F
). Zmuszasz dopasowanie do całej linii (-x
) i wypisujesz tylko te linie, które nie pasują (-v
). Dlatego drukujesz linie w pliku A, które nie zawierają tych samych danych, co dowolna linia w pliku B.Minusem tego rozwiązania jest to, że nie bierze ono pod uwagę kolejności linii, a jeśli dane wejściowe mają zduplikowane linie w różnych miejscach, możesz nie otrzymać tego, czego oczekujesz. Rozwiązaniem tego jest użycie prawdziwego narzędzia porównywania, takiego jak
diff
. Możesz to zrobić, tworząc plik różnicowy o wartości kontekstu na 100% linii w pliku, a następnie analizując go pod kątem tylko linii, które zostałyby usunięte w przypadku konwersji pliku A do pliku B. (Uwaga: to polecenie usuwa również różnicę formatowanie po uzyskaniu właściwych wierszy).źródło
-u
faktycznie zajmuje parametr liczby, o ile nie następuje po nim spacja. Zaletą tego, co miałem wcześniej, jest to, że będzie działać z wartością lub bez, więc możesz użyć czegoś w tej procedurze podrzędnej, która nie zwraca danych wyjściowych. Z drugiej strony wielkie litery „-U” wymagają argumentu.diff
rurociąg działa wspaniale dzięki.grep
potrzebą. Przykład:grep -F -x -v -f <(sort fileB) <(sort fileA)
diff
jest to, że pozycja w pliku jest brana pod uwagę.Odpowiedź zależy w dużej mierze od rodzaju i formatu porównywanych plików.
Jeśli porównywane pliki są posortowanymi plikami tekstowymi, narzędzie GNU napisane przez Richarda Stallmana i Davide McKenzie
comm
może wywołać filtrowanie, którego szukasz. Jest częścią coreutils.Przykład
Załóżmy, że masz 2 następujące pliki:
Linie w pliku
b
, których nie ma w plikua
:źródło
comm
; niestetycomm
wymaga posortowanych plików<()
? Działa i rozumiem, ale czy istnieje nazwa tej dziwności?<()
jest również znany jako podstawienie procesu .comm
został pierwotnie napisany około 1973 roku przez kogoś z Bell Labs, a nie rms. Mówisz o implementacji GNU, która pojawiła się dużo później. Przez lata istniało wiele różnych implementacji narzędzi uniksowych.z przepełnienia stosu ...
-23 pomija wiersze znajdujące się w obu plikach lub tylko w pliku 2. Pliki muszą zostać posortowane (są one w twoim przykładzie), ale jeśli nie, najpierw przeprowadź je przez sortowanie ...
Zobacz stronę podręcznika tutaj
źródło
Metody grep i comm (z sortowaniem) zajmują dużo czasu w przypadku dużych plików. SiegeX i ghostdog74 udostępniają dwie świetne metody awk do wyodrębniania linii unikatowych dla jednego z dwóch plików w przepełnieniu stosu:
źródło
Jeśli pliki są duże i nie masz niestandardowego porządku dla swoich wpisów, grep trwa o wiele za długo. Szybka alternatywa byłaby
[plik2-plik1 wyniki do ekranu, potok do pliku itp.]
Zmiana
>
na<
uzyskałaby przeciwne odjęcie.rm 1 2
źródło
Możesz również rozważyć vimdiff, to podkreśla różnice między plikami w edytorze vim
źródło