Jak korzystać z polecenia join w systemie Linux
Jeżeli chcesz połączyć dane z dwóch plików tekstowych, bazując na wspólnym polu, możesz skorzystać z polecenia join w systemie Linux. To narzędzie dodaje dynamikę do statycznych zbiorów danych. W tym artykule pokażemy, jak z niego korzystać.
Łączenie danych w plikach
Dane stanowią kluczowy element w działalności różnych organizacji, od korporacji po gospodarstwa domowe. Jednakże, gdy dane są przechowywane w różnych plikach i przez różne osoby, ich zarządzanie staje się problematyczne. Należy nie tylko wiedzieć, które pliki otworzyć, aby znaleźć potrzebne informacje, ale także radzić sobie z różnorodnością układów i formatów plików.
Do tego dochodzi również problem administracyjny związany z aktualizacją plików, archiwizacją starszych wersji oraz zarządzaniem tym, co wymaga zmiany, a co już zostało zaktualizowane.
Jeśli natomiast potrzebujesz skonsolidować dane lub przeprowadzić analizy na dużych zbiorach, napotykasz dodatkowy problem. Jak zorganizować i uporządkować dane rozproszone w różnych plikach, zanim przystąpisz do dalszej pracy? Jak zrealizować etap przygotowania danych?
Na szczęście, jeżeli pliki zawierają chociaż jedno wspólne pole, polecenie join w systemie Linux może być Twoim ratunkiem.
Przygotowanie plików danych
Do demonstracji użyjemy fikcyjnych danych z dwóch plików, które prezentują następujące zawartości:
cat file-1.txt
cat file-2.txt

Poniżej znajduje się zawartość pliku-1.txt:
1 Adore Varian [email protected] Female 192.57.150.231 2 Nancee Merrell [email protected] Female 22.198.121.181 3 Herta Friett [email protected] Female 33.167.32.89 4 Torie Venmore [email protected] Female 251.9.204.115 5 Deni Sealeaf [email protected] Female 210.53.81.212 6 Fidel Bezley [email protected] Male 72.173.218.75 7 Ulrikaumeko Standen [email protected] Female 4.204.0.237 8 Odell Jursch [email protected] Male 1.138.85.117
Każda linia w tym pliku zawiera następujące informacje:
Numer
Imię
Nazwisko
Adres e-mail
Płeć
Adres IP
1 Varian [email protected] Female Western New York $535,304.73 2 Merrell [email protected] Female Finger Lakes $309,033.10 3 Friett [email protected] Female Southern Tier $461,664.44 4 Venmore [email protected] Female Central New York $175,818.02 5 Sealeaf [email protected] Female North Country $126,690.15 6 Bezley [email protected] Male Mohawk Valley $366,733.78 7 Standen [email protected] Female Capital District $674,634.93 8 Jursch [email protected] Male Hudson Valley $663,821.09
Wiersze w tym pliku zawierają następujące informacje:
Numer
Nazwisko
Adres e-mail
Płeć
Region Nowego Jorku
Wartość w dolarach
Polecenie join łączy dane na podstawie "pól", które w tym kontekście oznaczają fragmenty tekstu oddzielone białymi znakami, końcem lub początkiem wiersza. Aby połączenie mogło zadziałać, każde wiersz w obu plikach musi posiadać wspólne pole.
Możemy użyć adresu e-mail, ponieważ jest on obecny w obu plikach i jest unikalny dla każdej osoby. Po szybkim przeglądzie plików możemy także zauważyć, że wiersze odpowiadają tym samym osobom, co pozwala użyć numerów linii jako pola do dopasowania (później możemy użyć innego pola).
Warto zwrócić uwagę, że oba pliki mają różną liczbę pól, co jest akceptowalne – możemy określić, które pole będzie użyte z każdego z plików.
Uważaj jednak na pola, takie jak regiony Nowego Jorku; w pliku rozdzielanym spacjami każde słowo w nazwie regionu traktowane jest jak osobne pole. Ponieważ niektóre regiony są nazywane dwu- lub trzysłownie, faktycznie masz różną liczbę pól w tym samym pliku. To nie stanowi problemu, o ile dopasujesz tylko te pola, które występują przed regionami.
Wykorzystanie polecenia join
Aby rozpocząć, pole, które zamierzasz dopasować, musi być posortowane. W obu plikach mamy rosnące numery, więc spełniamy to kryterium. Domyślnie, polecenie join używa pierwszego pola w pliku, co jest w naszym przypadku odpowiednie. Oczekuje również, że separatory pól będą białymi znakami, co również jest spełnione, więc możemy przejść do wykonania polecenia.
Używając wartości domyślnych, nasze polecenie będzie wyglądać następująco:
join file-1.txt file-2.txt

W tym przypadku, join traktuje pliki zgodnie z kolejnością, w jakiej są wymienione w poleceniu.
Wynikiem wykonania polecenia będzie:
1 Adore Varian [email protected] Female 192.57.150.231 Varian [email protected] Female Western New York $535,304.73 2 Nancee Merrell [email protected] Female 22.198.121.181 Merrell [email protected] Female Finger Lakes $309,033.10 3 Herta Friett [email protected] Female 33.167.32.89 Friett [email protected] Female Southern Tier $461,664.44 4 Torie Venmore [email protected] Female 251.9.204.115 Venmore [email protected] Female Central New York $175,818.02 5 Deni Sealeaf [email protected] Female 210.53.81.212 Sealeaf [email protected] Female North Country $126,690.15 6 Fidel Bezley [email protected] Male 72.173.218.75 Bezley [email protected] Male Mohawk Valley $366,733.78 7 Ulrikaumeko Standen [email protected] Female 4.204.0.237 Standen [email protected] Female Capital District $674,634.93 8 Odell Jursch [email protected] Male 1.138.85.117 Jursch [email protected] Male Hudson Valley $663,821.09
Wynik jest zaprezentowany w taki sposób, że najpierw pojawia się pole, na którym dopasowano wiersze, następnie pozostałe pola z pierwszego pliku, a na końcu pola z drugiego pliku, z pominięciem pola dopasowania.
Problemy z niesortowanymi danymi
Spróbujmy przypadku, w którym wiemy, że nie zadziała. Umieścimy wiersze w jednym z plików w nieodpowiedniej kolejności, co sprawi, że polecenie join nie będzie mogło poprawnie przetworzyć danych. Zawartość pliku-3.txt jest identyczna jak plik-2.txt, ale ósmy wiersz znajduje się pomiędzy piątym a szóstym.
Poniżej znajduje się zawartość pliku-3.txt:
1 Varian [email protected] Female Western New York $535,304.73 2 Merrell [email protected] Female Finger Lakes $309,033.10 3 Friett [email protected] Female Southern Tier $461,664.44 4 Venmore [email protected] Female Central New York $175,818.02 5 Sealeaf [email protected] Female North Country $126,690.15 8 Jursch [email protected] Male Hudson Valley $663,821.09 6 Bezley [email protected] Male Mohawk Valley $366,733.78 7 Standen [email protected] Female Capital District $674,634.93
Wpisujemy polecenie, aby spróbować połączyć plik-3.txt z plikiem-1.txt:
join file-1.txt file-3.txt

W wyniku działania polecenia join, otrzymujemy informację, że siódmy wiersz w pliku-3.txt jest nieprawidłowy, więc nie zostaje przetworzony. Linia ta zaczyna się od liczby sześć, która powinna znajdować się przed ósmą na prawidłowo posortowanej liście. Ostatni przetworzony wiersz to ten, który zaczyna się od „8 Odell”.
Możesz użyć opcji –check-order, aby sprawdzić, czy pliki są poprawnie posortowane – w przeciwnym razie join nie podejmie próby ich połączenia.
Wpisujemy:
join --check-order file-1.txt file-3.txt

Join informuje nas, że wystąpił problem z linią siódmą w pliku file-3.txt.
Pliki z brakującymi wierszami
W pliku-4.txt usunięto ostatnią linię, więc brakuje ósmego wiersza. Zawartość pliku jest następująca:
1 Varian [email protected] Female Western New York $535,304.73 2 Merrell [email protected] Female Finger Lakes $309,033.10 3 Friett [email protected] Female Southern Tier $461,664.44 4 Venmore [email protected] Female Central New York $175,818.02 5 Sealeaf [email protected] Female North Country $126,690.15 6 Bezley [email protected] Male Mohawk Valley $366,733.78 7 Standen [email protected] Female Capital District $674,634.93
Wprowadzamy następujące polecenie i, co zaskakujące, join nie zgłasza żadnych błędów i przetwarza wszystkie dostępne wiersze:
join file-1.txt file-4.txt

Wynik zawiera siedem połączonych wierszy.
Opcja -a (print unpaired) pozwala na wyświetlenie również wierszy, których nie można połączyć.
Aby polecenie join wypisało wiersze z pliku pierwszego, których nie można dopasować, wpisujemy:
join -a 1 file-1.txt file-4.txt

Wynik pokazuje siedem połączonych wierszy oraz linię ósmą z pliku pierwszego, która nie została dopasowana. Nie ma informacji o scaleniu, ponieważ plik-4.txt nie zawierał ósmego wiersza, do którego mogłaby zostać dopasowana. Jednakże, linia ta jest obecna w wyniku, więc można stwierdzić, że brak dopasowania jest wynikiem braku danych w pliku-4.txt.
Wprowadzając polecenie -v (pomijanie połączonych linii), możemy zobaczyć wszystkie linie, które nie pasują:
join -v file-1.txt file-4.txt

Widzimy, że jedyną linią, która nie ma dopasowania w pliku drugim, jest ósmy wiersz.
Dopasowywanie innych pól
Teraz spróbujmy połączyć dwa nowe pliki, korzystając z pola, które nie jest domyślne (pierwsze pole). Oto zawartość pliku-7.txt:
[email protected] Female 192.57.150.231 [email protected] Female 210.53.81.212 [email protected] Male 72.173.218.75 [email protected] Female 33.167.32.89 [email protected] Female 22.198.121.181 [email protected] Male 1.138.85.117 [email protected] Female 251.9.204.115 [email protected] Female 4.204.0.237
A oto zawartość pliku-8.txt:
Female [email protected] Western New York $535,304.73 Female [email protected] North Country $126,690.15 Male [email protected] Mohawk Valley $366,733.78 Female [email protected] Southern Tier $461,664.44 Female [email protected] Finger Lakes $309,033.10 Male [email protected] Hudson Valley $663,821.09 Female [email protected] Central New York $175,818.02 Female [email protected] Capital District $674,634.93
W tym przypadku, jedynym sensownym polem do połączenia jest adres e-mail, który jest pierwszym polem w pliku pierwszym i drugim polem w pliku drugim. Aby to uwzględnić, użyjemy opcji -1 (pierwszy plik, pierwsze pole) oraz -2 (drugi plik, drugie pole). Następnie podamy numer, który wskazuje, które pole w każdym pliku ma być użyte do połączenia.
Aby polecenie join wykorzystało pierwsze pole w pliku pierwszym oraz drugie pole w pliku drugim, wprowadzamy:
join -1 1 -2 2 file-7.txt file-8.txt

Pliki są łączone na podstawie adresu e-mail, który pojawia się jako pierwsze pole w wynikach.
Używanie różnych separatorów pól
A co, jeśli pliki mają pola oddzielone innymi znakami niż białe znaki?
Poniższe dwa pliki są rozdzielane przecinkami – jedyna spacja występuje między nazwami miejsc składającymi się z wielu słów:
cat file-5.txt
cat file-6.txt

Możemy użyć opcji -t (separator), aby wskazać, którego znaku użyć jako separatora pól. W tym przypadku używamy przecinka, w związku z czym wpiszemy następujące polecenie:
join -t, file-5.txt file-6.txt

Wszystkie wiersze zostały dopasowane, a spacje zostały zachowane w nazwach miejsc.
Ignorowanie wielkości liter
Inny plik, file-9.txt, jest niemal identyczny z file-8.txt. Jedyną różnicą jest to, że niektóre adresy e-mail mają wielkie litery, co przedstawiono poniżej:
Female [email protected] Western New York $535,304.73 Female [email protected] North Country $126,690.15 Male [email protected] Mohawk Valley $366,733.78 Female [email protected] Southern Tier $461,664.44 Female [email protected] Finger Lakes $309,033.10 Male [email protected] Hudson Valley $663,821.09 Female [email protected] Central New York $175,818.02 Female [email protected] Capital District $674,634.93
Podczas łączenia plików file-7.txt i file-8.txt wszystko działało idealnie. Zobaczmy, co się stanie, gdy połączymy file-7.txt z file-9.txt.
Wpisujemy:
join -1 1 -2 2 file-7.txt file-9.txt

W tym przypadku dopasowano jedynie sześć linii. Różnice w wielkości liter uniemożliwiły połączenie pozostałych dwóch adresów e-mail.
Wpisujemy:
join -1 1 -2 2 -i file-7.txt file-9.txt

Wszystkie osiem linii zostało dopasowanych i pomyślnie połączonych.
Mieszanie i łączenie danych
Polecenie join jest potężnym narzędziem, które może okazać się niezwykle przydatne w trudnych zadaniach związanych z przygotowaniem danych. Bez względu na to, czy musisz przeanalizować dane, czy też przekształcić je w celu importu do innego systemu, z pewnością docenisz, że masz je w swoim arsenale!