2009-10-15 13 views
16

Nie używaj żadnego języka programowania. Używaj tylko wyrażeń regularnych. Czy to możliwe?znajdź duplikaty wierszy i usuń je, używając wyrażenia regularnego z funkcją zamiany

Na przykład wejście >>

11 
22 
22 <-must remove 
33 
44 
44 <-must remove 
55 

Output >>

11 
22 
33 
44 
55 
+7

Wyrażenia regularne są wykonywane przez niektóre programy (SED, PERL, PYTHON, JAVA, coś). "Nie używaj żadnego języka programowania" nie ma sensu. Który program uruchamia wyrażenie regularne? –

+0

Tak, a poza tym, co powiedział S.Lott, musisz określić lepiej, co masz na myśli przez "usuń". Usunąć wszystkie wystąpienia zduplikowanych linii? Lub usunąć all-but-one? Jeśli to drugie, które chciałbyś zachować, pierwsze czy ostatnie? Czy kolejność nie ma znaczenia? – Davide

+0

Wreszcie, czy powinien przebiegać w jednym przejściu, czy dozwolone są wielokrotne przebiegi? – Davide

Odpowiedz

42

Regular-expressions.info ma stronę na Deleting Duplicate Lines From a File

To w zasadzie sprowadza się do poszukiwania tego oneliner:

^(.*)(\r?\n\1)+$ 

... I zastąpienie przez \1.
Uwaga: Dot nie musi pasować do nowej linii

Objaśnienie:

caret będzie pasował tylko na początku linii. Tak więc silnik regex będzie próbował tylko dopasować pozostałą część regexu. Kombinacja dot i star po prostu dopasowuje całą linię, niezależnie od jej zawartości, jeśli taka istnieje. Nawiasy przechowuje dopasowaną linię do pierwszej referencji zwrotnej.

Następnie dopasujemy separator linii. Umieszczam question mark w \r?\n, aby zrobić to wyrażenie regularne z plikami tekstowymi Windows (\r\n) i UNIX (\n). Do tego momentu dopasowaliśmy linię i następujący podział linii.

Teraz musimy sprawdzić, czy po tej kombinacji występuje duplikat tej samej linii. Robimy to po prostu z \1. Jest to pierwsza referencja zwrotna, która zawiera dopasowaną linię. Odniesienie będzie pasować do tego samego tekstu.

Jeśli odwołanie zwrotne nie pasuje, dopasowanie regex i odwołanie zwrotne są odrzucane, a silnik wyrażeń regularnych próbuje ponownie na początku następnego wiersza. Jeśli odwołanie zwrotne się powiedzie, w wyrażeniu regularnym plus symbol spróbuje dopasować dodatkowe kopie wiersza. Na koniec, dollar symbol zmusza silnik regex do sprawdzenia, czy tekst dopasowany przez referencję zwrotną jest kompletną linią. Wiemy już, że tekst dopasowany przez referencję wsteczną jest poprzedzony linią podziału (dopasowaną przez \ r? \ N). Dlatego teraz sprawdzamy, czy po nim występuje podział wiersza lub czy znajduje się na końcu pliku przy użyciu dollar sign.

Cały mecz zamieni się na line\nline (lub line\nline\nline itd.). Ponieważ przeprowadzamy wyszukiwanie i zamieniamy, wiersz, jego duplikaty i linia między nimi są usuwane z pliku. Ponieważ chcemy, aby zachować oryginalną linię, ale nie duplikaty, używamy \1 jako tekstu zastępczego umieścić oryginalną linię widok.

3

Zobacz moją prośbę o więcej informacji, jestem odpowiadając w łatwy teraz droga.

  1. Jeżeli kolejność nie ma znaczenia, po prostu

    sort -u

    rade

  2. Jeśli kolejność ma znaczenie, ale nie przeszkadza re- uruchomić wiele przejść (to jest składnia vim), można użyć:

    % s/\ (*. \) \ (\ _ *. \) \ (\ 1 \)/\ 2 \ 1/g

    zachowania ostatniego wystąpienia lub

    % s/\ (. * \) \ (\ _. * \) \ (\ 1 \)/\ 1 \ 2/g

    w celu zachowania pierwsze wystąpienie.

Jeśli nie masz nic przeciwko ponownemu uruchomieniu wielu przebiegów, to jest to trudniejsze, więc zanim to zrobimy, powiedz to w pytaniu!

EDYCJA: w twojej edycji nie byłeś zbyt klarowny, ale wygląda na to, że chcesz tylko jednokrotne zduplikowanie linii ADJACENT! Cóż, to znacznie łatwiejsze!

Prosty:

/(.*)\1*/\1/ 

(/\(.*\)\1*/\1/ w vim), czyli poszukiwanie (.*)\1* i zastąpienie go tylko \1 rade

+0

'(. *) \ 1 *' nie pasuje do powtarzających się linii, ponieważ w regexie nie ma nic zgodnego z linią podziału między linią a jej duplikatem. –

3

W RegexBuddy Można to zrobić w następujący sposób:

  1. Na karcie Biblioteka wczytaj bibliotekę RegexBuddy.rbl, jeśli nie jest ona załadowana domyślnie.
  2. W polu wyszukiwania wpisz "duplikat"
  3. Kliknij przycisk Użyj, aby załadować wyrażenie "usuń duplikaty wierszy".
  4. Na karcie GREP określ folder i maskę plików, z których chcesz usunąć duplikaty.
  5. Z rozwijanego menu przycisku GREP wybierz opcję Wykonaj.

Jeśli robisz to tylko w jednym pliku, możesz użyć karty Test zamiast karty GREP. Załaduj plik na kartę Test, a następnie kliknij przycisk Zamień na głównym pasku narzędzi.

Powiązane problemy