Mam swoje referencje jako plik tekstowy z długą listą wpisów, a każda z nich ma dwa (lub więcej) pól.
Pierwsza kolumna to adres URL odwołania; druga kolumna to tytuł, który może się nieco różnić w zależności od tego, w jaki sposób dokonano wpisu. To samo dla trzeciego pola, które może być obecne lub nie.
Chcę zidentyfikować, ale nie usunąć wpisów, które mają identyczne pierwsze pole (URL referencyjny). Wiem o sort -k1,1 -u
tym, ale to automatycznie (nieinteraktywnie) usunie wszystkie oprócz pierwszego trafienia. Czy jest jakiś sposób, aby poinformować mnie, żebym mógł wybrać, który zachować?
W poniższym wyciągu z trzech linii, które mają to samo pierwsze pole ( http://unix.stackexchange.com/questions/49569/
), chciałbym zachować linię 2, ponieważ ma ona dodatkowe tagi (sort, CLI) i usuwa linie nr 1 i nr 3:
http://unix.stackexchange.com/questions/49569/ unique-lines-based-on-the-first-field
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field sort, CLI
http://unix.stackexchange.com/questions/49569/ Unique lines based on the first field
Czy istnieje program ułatwiający identyfikację takich „duplikatów”? Czy mogę ręcznie wyczyścić, usuwając osobiście wiersze nr 1 i nr 3?
źródło
Odpowiedzi:
Jeśli rozumiem twoje pytanie, myślę, że potrzebujesz czegoś takiego:
lub:
gdzie
file.txt
twój plik zawierający dane o tobie są zainteresowani.Na wyjściu zobaczysz liczbę linii i linii, w których pierwsze pole znajduje się dwa lub więcej razy.
źródło
cut -d " " -f1 file.txt | uniq -d
daje mi niezły wynik.Jest to klasyczny problem, który można rozwiązać za pomocą
uniq
polecenia.uniq
może wykrywać duplikaty kolejnych linii i usuwać duplikaty (-u
,--unique
) lub zachować tylko duplikaty (-d
,--repeated
).Ponieważ zamawianie zduplikowanych linii nie jest dla Ciebie ważne, powinieneś je najpierw posortować. Następnie użyj,
uniq
aby wydrukować tylko unikalne linie:Istnieje również opcja
-c
(--count
), która drukuje liczbę duplikatów tej-d
opcji. Szczegółowe informacje można znaleźć na stronie podręcznika użytkownikauniq
.Jeśli naprawdę nie przejmujesz się częściami po pierwszym polu, możesz użyć następującego polecenia, aby znaleźć duplikaty kluczy i wydrukować dla nich każdy numer wiersza (dodaj kolejny,
| sort -n
aby sortować dane wyjściowe według wiersza):Ponieważ chcesz zobaczyć zduplikowane linie (używając pierwszego pola jako klucza), nie możesz bezpośrednio użyć
uniq
. Problemem utrudniającym automatyzację jest to, że części tytułowe różnią się, ale program nie może automatycznie określić, który tytuł należy uznać za ostateczny.Oto skrypt AWK (zapisz go
script.awk
), który pobiera plik tekstowy jako dane wejściowe i drukuje wszystkie zduplikowane linie, abyś mógł zdecydować, który plik usunąć. (awk -f script.awk yourfile.txt
)źródło
-w
(--check-chars
) ograniczenia do określonej liczby znaków, ale na przykładzie masz zmienne pierwsze pola. Ponieważuniq
nie obsługuje wyboru pola, musisz użyć obejścia. Podam przykład AWK, ponieważ jest to łatwiejsze.-w
ale długość pierwszego pola jest zmienna :(Jeśli dobrze to przeczytam, wystarczy coś takiego
Spowoduje to wydrukowanie numeru linii zawierającej duplikat i samej linii. Na przykład za pomocą tego pliku:
Wyprodukuje ten wynik:
Aby wydrukować tylko numer linii, możesz to zrobić
I aby wydrukować tylko linię:
Wyjaśnienie:
awk
Skrypt po prostu drukuje 1st przestrzeń oddziela pole pliku. Służy$N
do drukowania N-tego pola.sort
sortuje je iuniq -c
liczy wystąpienia każdej linii.Jest on następnie przekazywany do
while
pętli, która zapisuje liczbę wystąpień as,$num
a linia as$dupe
i if$num
jest większa niż jeden (więc jest zduplikowana co najmniej raz), przeszuka plik dla tej linii, używając-n
do wydrukowania numeru linii.--
Mówigrep
, że co za tym idzie nie jest to opcja wiersza polecenia, przydatne do kiedy$dupe
można zacząć-
.źródło
Bez wątpienia najbardziej wyczerpujący na liście może być prawdopodobnie krótszy:
daje plik tekstowy taki jak:
wyjście takie jak:
Po wybraniu linii do usunięcia:
źródło
Zobacz następujące posortowane
file.txt
:Ponieważ lista jest krótka, po sortowaniu widzę, że istnieją trzy zestawy duplikatów.
Następnie mogę na przykład zachować:
zamiast
Ale w przypadku dłuższej listy będzie to trudne. Na podstawie dwóch odpowiedzi, z których jedna sugeruje,
uniq
a druga sugerujecut
, stwierdzam, że to polecenie daje mi wynik, który chciałbym:źródło
cut
. Jeśli wykonujesz pracę polegającą na usuwaniu duplikatów, numery linii mogą być bardzo pomocne. Aby wydrukować wszystkie duplikaty, użyj-D
opcji zamiast-d
.for dup in $(cut -d " " -f1 file.txt | uniq -d); do grep -n $dup file.txt; done
jak w mojej odpowiedzi. To da ci lepszy podgląd tego, co Cię interesuje.Właśnie tak to rozwiązałam:
plik_z duplikatami:
Plik posortowany i deduponowany według kolumn 1 i 2:
Plik posortowany tylko według kolumn 1 i 2:
Pokaż tylko różnicę:
źródło