Próbowałem diff, ale generuje kilka liczb i innych symboli przed różnymi wierszami, co utrudnia mi porównywanie plików.
niedziela,
Odpowiedzi:
216
diff (1) nie jest odpowiedzią, ale comm (1) jest.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
Więc
comm -2-3 file1 file2 > file3
Pliki wejściowe muszą zostać posortowane. Jeśli tak nie jest, najpierw je posortuj. Można to zrobić za pomocą pliku tymczasowego lub ...
comm -2-3<(sort file1)<(sort file2)> file3
pod warunkiem, że twoja powłoka obsługuje podstawianie procesów (bash tak).
Pamiętaj, że dwa pliki muszą być posortowane i są unikalne
andy
6
Możesz pogrupować opcje razem:comm -23
Paolo M
Co oznacza „posortowane”? Że linie mają tę samą kolejność? Wtedy prawdopodobnie jest w porządku w większości przypadków użycia - tak jak w przypadku sprawdzania, które linie zostały dodane, porównując ze starszą wersją z kopią zapasową. Jeśli nowo dodane linie nie mogą znajdować się między istniejącymi liniami, jest to większy problem.
Egor Hans
@EgorHans: jeśli plik zawiera np. Wiersze zawierające liczby całkowite, takie jak „3 \ n1 \ n3 \ n2 \ n”, to wiersze należy najpierw uporządkować w kolejności rosnącej lub malejącej, np. „\ 1 \ n2 \ n3 \ n3 \ n” z duplikatami sąsiadujący. To jest „posortowane” i oba pliki muszą być posortowane w podobny sposób. Gdy nowszy plik ma nowe wiersze, nie ma znaczenia, czy znajdują się one „między istniejącymi wierszami”, ponieważ po sortowaniu ich nie ma, są w kolejności posortowanej.
sorpigal
48
Narzędzie Unix diffjest przeznaczone dokładnie do tego celu.
$ diff -u file1 file2 > file3
Więcej informacji na temat opcji, różnych formatów wyjściowych itp. Można znaleźć w instrukcji i w Internecie.
Istnieją dwa ograniczenia tej odpowiedzi: (1) działa tylko dla krótkich linii (domyślnie mniej niż 80 znaków, chociaż można to zmienić) i, co ważniejsze, (2) dodaje „<” na końcu każdego linia, która musi zostać usunięta przez inny program (np. awk, sed).
sergut
W wielu przypadkach będziesz również chciał użyć -d, który postara się diffznaleźć najmniejszą możliwą różnicę. -i, -E, -w, -BI --suppress-blank-emptymoże być także przydatny czasami, choć nie zawsze. Jeśli nie wiesz, co pasuje do twojego przypadku użycia, spróbuj diff --helpnajpierw (co jest ogólnie dobrym pomysłem, gdy nie wiesz, co może zrobić polecenie).
Egor Hans
Ponadto, używając --line-format =% L, powstrzymujesz diff przed generowaniem jakichkolwiek dodatkowych znaków (przynajmniej pomoc mówi, że działa w ten sposób, ale zaraz go wypróbujesz).
Czasami diffjest to narzędzie, którego potrzebujesz, ale czasami joinjest bardziej odpowiednie. Pliki muszą być wstępnie posortowane lub, jeśli używasz powłoki obsługującej podstawianie procesów, takiej jak bash, ksh lub zsh, możesz sortować w locie.
Powinieneś dostać za to medal! To było dokładnie to, czego szukałem przez ostatnie 2 godziny
Zatarra
7
Próbować
sdiff file1 file2
Zwykle działa znacznie lepiej w większości przypadków. Możesz chcieć posortować pliki wcześniej, jeśli kolejność linii nie jest ważna (np. Niektóre tekstowe pliki konfiguracyjne).
Niezłe narzędzie! Uwielbiam to, jak zaznacza zróżnicowane linie. Znacznie ułatwia porównywanie konfiguracji. To razem z sdiff <(sort file1) <(sort file2)
sortem
3
Jeśli chcesz rozwiązać ten problem za pomocą coreutils, akceptowana odpowiedź jest dobra:
comm -23<(sort file1)<(sort file2)> file3
Możesz także użyć sd (stream diff), który nie wymaga sortowania ani podstawiania procesów i obsługuje nieskończone strumienie, na przykład:
cat file1 | sd 'cat file2'> file3
Prawdopodobnie nie jest to duża korzyść w tym przykładzie, ale nadal rozważ to; w niektórych przypadkach nie będzie w stanie wykorzystać commani grep -Fani diff.
Oto post na blogu, który napisałem o różnicowaniu strumieni na terminalu, który wprowadza sd.
Wiele odpowiedzi już jest, ale żadna z nich nie jest idealna IMHO. Odpowiedź Thanatosa pozostawia kilka dodatkowych znaków w linii, a odpowiedź Sorpigala wymaga sortowania lub wstępnego sortowania plików, co może nie być odpowiednie w każdych okolicznościach.
Myślę, że najlepszym sposobem na uzyskanie linii, które są różne i nic innego (bez dodatkowych znaków, bez ponownego zamawiania) jest kombinacją diff, grepi awk(lub podobny).
Jeśli wiersze nie zawierają znaku „<”, krótką linijką może być:
diff urls.txt*| grep "<"| sed 's/< //g'
ale to usunie każde wystąpienie „<” (mniej niż, spacja) z linii, co nie zawsze jest OK (np. kod źródłowy). Najbezpieczniejszą opcją jest użycie awk:
Ta jedna linijka porównuje oba pliki, następnie filtruje wyjście diff w stylu ed, a następnie usuwa końcowe „<”, które dodaje diff. Działa to nawet wtedy, gdy linie zawierają same „<”.
Wypróbowałem prawie wszystkie odpowiedzi w tym wątku, ale żadna nie była kompletna. Po kilku szlakach powyżej jeden zadziałał. diff da ci różnicę, ale z pewnymi niechcianymi specjalnymi charasami. gdzie rzeczywiste linie różnicy zaczynają się od „>”. więc następnym krokiem jest grep linie zaczynające się od '>', po którym następuje usunięcie tego samego z sedem .
To jest zły pomysł. Będziesz także musiał zmodyfikować linie zaczynające się od <. Zobaczysz to, jeśli zmienisz kolejność plików wejściowych. Nawet jeśli to zrobiłeś, chciałbyś ominąć grepużywając więcej sed: `diff a1 a2 | sed '/> / s ///' 'Może to nadal przerywać linie zawierające >lub <w odpowiedniej sytuacji i nadal pozostawia dodatkowe linie opisujące numery linii. Jeśli chciał spróbować tego podejścia jest lepszym sposobem byłoby: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'.
--old-line-format='', wyłącz wyjście dla plik1, jeśli linia różniła się od porównania w pliku2. --unchanged-line-format='', wyłącz wyjście, jeśli linie są takie same.
Odpowiedzi:
diff (1) nie jest odpowiedzią, ale comm (1) jest.
Więc
Pliki wejściowe muszą zostać posortowane. Jeśli tak nie jest, najpierw je posortuj. Można to zrobić za pomocą pliku tymczasowego lub ...
pod warunkiem, że twoja powłoka obsługuje podstawianie procesów (bash tak).
źródło
comm -23
Narzędzie Unix
diff
jest przeznaczone dokładnie do tego celu.Więcej informacji na temat opcji, różnych formatów wyjściowych itp. Można znaleźć w instrukcji i w Internecie.
źródło
Rozważ to:
plik a.txt:
plik b.txt:
Możesz znaleźć różnicę w:
Wynik będzie:
Możesz przekreślić wynik w pliku wyjściowym (c.txt) za pomocą:
To odpowie na twoje pytanie:
źródło
-d
, który postara siędiff
znaleźć najmniejszą możliwą różnicę.-i
,-E
,-w
,-B
I--suppress-blank-empty
może być także przydatny czasami, choć nie zawsze. Jeśli nie wiesz, co pasuje do twojego przypadku użycia, spróbujdiff --help
najpierw (co jest ogólnie dobrym pomysłem, gdy nie wiesz, co może zrobić polecenie).Czasami
diff
jest to narzędzie, którego potrzebujesz, ale czasamijoin
jest bardziej odpowiednie. Pliki muszą być wstępnie posortowane lub, jeśli używasz powłoki obsługującej podstawianie procesów, takiej jak bash, ksh lub zsh, możesz sortować w locie.źródło
Próbować
Zwykle działa znacznie lepiej w większości przypadków. Możesz chcieć posortować pliki wcześniej, jeśli kolejność linii nie jest ważna (np. Niektóre tekstowe pliki konfiguracyjne).
Na przykład,
źródło
sdiff <(sort file1) <(sort file2)
Jeśli chcesz rozwiązać ten problem za pomocą coreutils, akceptowana odpowiedź jest dobra:
Możesz także użyć sd (stream diff), który nie wymaga sortowania ani podstawiania procesów i obsługuje nieskończone strumienie, na przykład:
Prawdopodobnie nie jest to duża korzyść w tym przykładzie, ale nadal rozważ to; w niektórych przypadkach nie będzie w stanie wykorzystać
comm
anigrep -F
anidiff
.Oto post na blogu, który napisałem o różnicowaniu strumieni na terminalu, który wprowadza sd.
źródło
Jednak nie ma
grep
rozwiązania?linie, które istnieją tylko w pliku2:
linie, które istnieją tylko w pliku1:
linie, które istnieją w obu plikach:
źródło
Wiele odpowiedzi już jest, ale żadna z nich nie jest idealna IMHO. Odpowiedź Thanatosa pozostawia kilka dodatkowych znaków w linii, a odpowiedź Sorpigala wymaga sortowania lub wstępnego sortowania plików, co może nie być odpowiednie w każdych okolicznościach.
Myślę, że najlepszym sposobem na uzyskanie linii, które są różne i nic innego (bez dodatkowych znaków, bez ponownego zamawiania) jest kombinacją
diff
,grep
iawk
(lub podobny).Jeśli wiersze nie zawierają znaku „<”, krótką linijką może być:
ale to usunie każde wystąpienie „<” (mniej niż, spacja) z linii, co nie zawsze jest OK (np. kod źródłowy). Najbezpieczniejszą opcją jest użycie awk:
Ta jedna linijka porównuje oba pliki, następnie filtruje wyjście diff w stylu ed, a następnie usuwa końcowe „<”, które dodaje diff. Działa to nawet wtedy, gdy linie zawierają same „<”.
źródło
Jestem zaskoczony, że nikt nie wspomniał
diff -y
o tworzeniu równoległego wyjścia , na przykład:A w
file3
(różne linie mają symbol|
w środku):źródło
Użyj narzędzia Diff i wyodrębnij tylko wiersze zaczynające się od <w danych wyjściowych
źródło
Wypróbowałem prawie wszystkie odpowiedzi w tym wątku, ale żadna nie była kompletna. Po kilku szlakach powyżej jeden zadziałał. diff da ci różnicę, ale z pewnymi niechcianymi specjalnymi charasami. gdzie rzeczywiste linie różnicy zaczynają się od „>”. więc następnym krokiem jest grep linie zaczynające się od '>', po którym następuje usunięcie tego samego z sedem .
źródło
<
. Zobaczysz to, jeśli zmienisz kolejność plików wejściowych. Nawet jeśli to zrobiłeś, chciałbyś ominąćgrep
używając więcej sed: `diff a1 a2 | sed '/> / s ///' 'Może to nadal przerywać linie zawierające>
lub<
w odpowiedniej sytuacji i nadal pozostawia dodatkowe linie opisujące numery linii. Jeśli chciał spróbować tego podejścia jest lepszym sposobem byłoby:diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.Możesz użyć
diff
z następującym formatowaniem wyjściowym:--old-line-format=''
, wyłącz wyjście dla plik1, jeśli linia różniła się od porównania w pliku2.--unchanged-line-format=''
, wyłącz wyjście, jeśli linie są takie same.źródło