Mam duży plik A (składający się z e-maili), jeden wiersz na każdą wiadomość. Mam też inny plik B zawierający inny zestaw wiadomości.
Którego polecenia użyłbym, aby usunąć wszystkie adresy, które pojawiają się w pliku B z pliku A.
Tak więc, jeśli plik A zawierał:
A
B
C
a plik B zawierał:
B
D
E
Następnie plik A należy pozostawić z:
A
C
Teraz wiem, że jest to pytanie, które mogło być zadawane częściej, ale znalazłem tylko jedno polecenie w Internecie, które dało mi błąd ze złym separatorem.
Każda pomoc będzie mile widziana! Ktoś na pewno wymyśli sprytny, jednoliniowy, ale ja nie jestem ekspertem od muszli.
Odpowiedzi:
Jeśli pliki są posortowane (są w twoim przykładzie):
-23
pomija wiersze, które są w obu plikach lub tylko w pliku 2. Jeśli pliki nie są posortowane, przepuść jesort
najpierw ...Zobacz stronę man tutaj
źródło
comm -23 file1 file2 > file3
wyświetli zawartość w plik1, a nie w plik2, do pliku3. A potemmv file3 file1
ostatecznie wyczyści zbędną zawartość w pliku1.comm -23 file1 file2 | sponge file1
. Nie jest potrzebne czyszczenie.grep -Fvxf <lines-to-remove> <all-lines>
Przykład:
Wynik:
Wyjaśnienie:
-F
: użyj ciągów literałów zamiast domyślnego BRE-x
: rozważ tylko mecze, które pasują do całej linii-v
: wypisz niezgodne-f file
: pobiera wzorce z podanego plikuTa metoda jest wolniejsza w przypadku wstępnie posortowanych plików niż inne metody, ponieważ jest bardziej ogólna. Jeśli liczy się również szybkość, zobacz: Szybki sposób znajdowania wierszy w jednym pliku, których nie ma w innym?
Oto szybka automatyzacja bash do pracy w linii:
GitHub upstream .
stosowanie:
Zobacz też: /unix/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another
źródło
awk na ratunek!
To rozwiązanie nie wymaga posortowanych danych wejściowych. Najpierw musisz podać plikB.
zwroty
Jak to działa?
Zauważ, że teraz można tego użyć do usunięcia słów z czarnej listy.
z niewielką zmianą może wyczyścić wiele list i utworzyć wyczyszczone wersje.
źródło
A\nC
, zapisać do pliku tymczasowego pierwszy i zastąpić oryginalny plik... > tmp && mv tmp fileA
fileB
nie jest puste (długość 0 bajtów), ponieważ jeśli tak, otrzymasz pusty wynik zamiast oczekiwanej zawartościfileA
. (Przyczyna:FNR==NR
będzie obowiązywaćfileA
wtedy.)Inny sposób na zrobienie tego samego (wymaga również posortowanych danych wejściowych):
W Bash, jeśli pliki nie są wstępnie posortowane:
źródło
Możesz to zrobić, chyba że Twoje pliki są posortowane
--new-line-format
dotyczy wierszy znajdujących się w pliku b, ale nie a,--old-..
dotyczy wierszy znajdujących się w pliku a, ale nie znajduje się w b,--unchanged-..
dotyczy wierszy znajdujących się w obu.%L
sprawia, że wiersz jest drukowany dokładnie.po więcej szczegółów
źródło
comm
polecenia.comm
wymaga sortowania plików, więc jeśli są posortowane, możesz również użyć tego rozwiązania. Możesz użyć tego rozwiązania niezależnie od tego, czy plik jest posortowany, czy nieTo udoskonalenie ładnej odpowiedzi @ karakfa może być zauważalnie szybsze w przypadku bardzo dużych plików. Podobnie jak w przypadku tej odpowiedzi, żaden plik nie musi być sortowany, ale szybkość jest zapewniona dzięki tablicom asocjacyjnym awk. W pamięci przechowywany jest tylko plik wyszukiwania.
Sformułowanie to dopuszcza również możliwość wykorzystania tylko jednego określonego pola ($ N) w pliku wejściowym w porównaniu.
(Kolejną zaletą tego podejścia jest to, że można łatwo zmodyfikować kryterium porównania, np. W celu przycięcia wiodących i końcowych białych znaków).
źródło
Możesz użyć Pythona:
źródło
Możesz użyć -
diff fileA fileB | grep "^>" | cut -c3- > fileA
Będzie to działać w przypadku plików, które nie są również posortowane.
źródło
Aby usunąć wspólne linie między dwoma plikami, możesz użyć polecenia grep, comm lub join.
Wyświetla wiersze z plik1, które nie pasują do żadnej linii w pliku2.
Wyświetla wiersze z plik1, które nie pasują do żadnej linii w pliku2.
źródło