Wyrażenie regularne do znajdowania podwójnych znaków w Bash

10

Szukam wyrażenia regularnego, które wyszukuje wszystkie wystąpienia podwójnych znaków w tekście, liście itp. W wierszu poleceń (Bash).

Głównym Pytanie : Czy istnieje prosty sposób do poszukiwania takich sekwencji aa, ll, ttttt, itd., Gdzie jeden definiuje wyrażenie regularne, które szuka n wystąpień tego samego znaku z? To, czego szukam, to osiągnięcie tego na bardzo podstawowym poziomie. W wierszu poleceń. W powłoce Linux.

Po kilku badaniach doszedłem do następujących odpowiedzi - i wynikających z nich pytań, dlatego dały mi one wskazówkę, gdzie może być rozwiązanie. Ale:

a) (e) grep i problem z odwrotnym ukośnikiem

  • grep 'a\{2\}' szuka aa
  • egrep'a{2}' szuka aa

Pytanie: Czy konieczność ustawienia luzów jest naprawdę związana z poleceniem, którego używam? Jeśli tak, to czy ktoś może dać mi wskazówkę, co jeszcze należy wziąć pod uwagę, używając tutaj (e) grep?

b) Znalazłem tutaj odpowiedź na moje pytanie, chociaż nie jest to dokładnie to, czego szukałem:

grep -E '(.)\1' filenameszuka wpisów z tym samym znakiem pojawiających się więcej niż jeden raz, ale nie pyta, jak często . To jest blisko tego, czego szukam, ale nadal chcę ustawić wiele powtórzeń.

Prawdopodobnie powinienem podzielić to na dwa lub więcej pytań, ale nie chcę tutaj zalewać tej niesamowitej strony.

PS: Jeszcze jedno pytanie, może nie na temat ale: czy to in, inside, atlub on the shell. I jest on the command linepoprawne?

erch
źródło

Odpowiedzi:

8

To naprawdę dwa pytania i powinny były zostać podzielone. Ale ponieważ odpowiedzi są stosunkowo proste, umieszczę je tutaj. Te odpowiedzi dotyczą grepkonkretnie GNU .

a) egrepjest taki sam jak grep -E. Oba wskazują, że zamiast grepdomyślnych wyrażeń regularnych należy używać „rozszerzonych wyrażeń regularnych” . grepwymaga odwrotnych ukośników dla zwykłych wyrażeń regularnych.

Ze manstrony:

Podstawowe i rozszerzone wyrażenia regularne

W podstawowych wyrażeniach regularnych metaznaki ? , + , { , | , ( i ) tracą swoje specjalne znaczenie; zamiast tego użyj wersji z odwrotnym ukośnikiem \? , \ + , \ { , \ | , \ ( i \) .

Zobacz manstronę, aby uzyskać dodatkowe informacje na temat konwencji historycznych i przenośności.

b) Użyj egrep '(.)\1{N}'i zamień Nna liczbę znaków, którą chcesz zastąpić minus jeden (ponieważ kropka pasuje do pierwszego). Więc jeśli chcesz dopasować znak powtórzony cztery razy, użyj egrep '(.)\1{3}'.

depquid
źródło
Podczas czytania strony podręcznika musiałem naprawdę źle zrozumieć lub źle zinterpretować wskazaną przez ciebie część. Kiedy przeszedłem kilka samouczków wyrażeń regularnych, nie było żadnych wskazówek na temat takiego zachowania. Myślałem, że Wyrażenie regularne oznacza coś na tak podstawowym poziomie, że większość aplikacji działa z tym samym zestawem symboli. Znów okazało się, że się mylę. Dzięki za pomoc! To mi naprawdę pomogło.
erch
Jest to również dość mylące czytanie „ zawsze używaj odwrotnego ukośnika, aby wziąć specjalne znaczenie ze znaków takich jak., +, Itp. ”, A następnie odkrywając, że na pozór przeciwnie jest reguła z najbardziej podstawowym poleceniem.
erch
@ cellar.dweller To mylące! Wiele uzasadnień ma charakter historyczny. Jestem bardziej zaznajomiony z formą rozszerzoną, więc mam zwyczaj, aby zawsze używać tylko, egrepjeśli potrzebuję wyrażeń regularnych (w przeciwieństwie do zwykłego dopasowywania ciągów), aby nie musiałem się martwić pamiętaniem różnic między grepnimi rodzaje wyrażeń regularnych.
depquid
4
Pamiętaj, że standardowe ERE nie obsługują referencji wstecznych, podczas gdy standardowe BRE. Więc grep '\(.\)\1\{3\}'jest standardem, grep -E '(.)\1{3}'nie jest.
Stéphane Chazelas,
7

To szukałoby 2 lub więcej wystąpień tej samej postaci:

grep -E '(.)\1+' file

Jeśli twój awk ma opcję -o, to wypisuje go za każdym razem w nowej linii.

grep -Eo '(.)\1+' file

Aby znaleźć mecze z dokładnie 3 dopasowaniami:

grep -E '(.)\1{2}' file

Lub 3 lub więcej:

grep -E '(.)\1{2,}' file

itp..


edytować

W rzeczywistości @stephane_chazelas ma rację co do referencji i -E. Zapomniałem o tym. Próbowałem go w BSD grep i GNU grep i działa tam, ale nie ma go w innych greps. Musisz użyć jednej z poniższych wersji ..

Zwykłe wersje grep:

grep '\(.\)\1\{1,\}' file

grep -o '\(.\)\1\{1,\}' file

grep '\(.\)\1\{2\}' file

grep '\(.\)\1\{2,\}' file

Ta -oopcja również nie jest standardowym grep BTW (prawdopodobnie jeśli twój grep rozumie -o, może również zrobić referencję wstecz).


Uwaga : grep -E '(.)\1{2,}'plik i grep '\(.\)\1\{2\}'plik są niepoprawne, jak wskazuje Alexis, i należy je zignorować.

Skrutator
źródło
Do tej pory dziękuję. Ale: mam rację mówiąc, że bez -Eopcji grepnie zrobi dużo? To by wyjaśniało całkiem sporo, na przykład dlaczego tak wiele czasu traciłem na szukanie, gdzie się mylę!
erch
Bez opcji -E możesz zrobić to samo w tym przypadku, ale musiałbyś uciec więcej i nie ma +operatora. Podam też przykłady.
Skrutinizer
Mała korekta: grep -E '(.)\1{2}'nie do końca „Znajdź dopasowania z dokładnie 3 dopasowaniami”. Chociaż będzie pasował dokładnie trzy identyczne znaki, mogą być osadzone w dłuższym powtarzanym ciągu; np. będzie pasować do ciągu 5-symbolowego AAAAA. (A jeśli jest 6 lub więcej kolejnych symboli, dopasuje się więcej niż jeden raz).
Alexis
Tak, masz absolutną rację, to nie działa zgodnie z przeznaczeniem, w rzeczywistości nie jest to możliwe ..
Scrutinizer
3

Po pierwsze, dziękuję wszystkim za komentarze i sugestie. Jak się okazuje, byłem już dość blisko odpowiedzi.

Głównym problemem było o:

Czy istnieje prosty sposób szukać n wystąpień tego samego znaku, na przykład aa,tttttt

Krótka odpowiedź :

Następujące [warianty] poleceń powtórzą aco najmniej jeden i nieskończony czas

grep 'a\{1,}

grep -E \(a\)\{1,\}

egrep a{1,}

lub z dostępnymi wyrażeniami regularnymi GNU grep a\+


Liczbę powtórzeń ustawia się w nawiasach klamrowych, poprzez wzór {min,max}{n}powtórz dokładnie nrazy, {n,}powtórz co najmniej nraz i {n,m}powtórz co najmniej, nale najczęściej m.

W związku z tym podniósł kwestię drugorzędną :

Czy konieczność ustawiania luzów jest związana z poleceniem, którego używam?

Krótka odpowiedź : Tak, użycie odwrotnych ukośników zależy od tego, czy się używa, grepczyegrep

  • grep: odwrotny ukośnik aktywuje metaznaki [używa podstawowych wyrażeń regularnych]
  • egrepbackslash de -activates metaznakami [używa rozszerzeń wyrażenia regularne]

Ponieważ jest to krótka odpowiedź, chcę przekazać tym, którzy napotkali podobne problemy, dodałem moje podstawowe podsumowanie tego, o czym na pozór trzeba być świadomym, pracując z grepi egrep.




Wyrażenia podstawowe, rozszerzone i GNU

Podstawowe wyrażenia regularne

Używany w grep, edi sedpolecenia

Podstawowe funkcje zestawu wyrażeń regularnych to:

  • Większość metaznaków, np. ? [ . \ )Itp., Jest aktywowanych za pomocą odwrotnego ukośnika. Jeśli nie wystąpi ukośnik odwrotny, będą one traktowane jako (część) wyszukiwanego terminu.
  • ^ $ \<i \>są obsługiwane bez ukośnika odwrotnego
  • Brak stenograficzne znaki [ \b, \sitp]

Podstawowe wyrażenia regularne GNU dodają je

  • \?powtórz znak zero lub jeden raz ( c\?mecze ci cc) i jest alternatywą dla\{0,1\}
  • \+Powtarzam postać co najmniej jeden raz ( c\+mecze cc, ccccccccitd) i jest alternatywą dla\{1,\}

  • \|jest obsługiwany (np. grep a\|bbędzie szukał alubb

grep -E włącza polecenie do korzystania z całego zestawu rozszerzonych wyrażeń regularnych:


Rozszerzone wyrażenia regularne [ERE]

Używany w egrep, awki emacsjest położony Basic Plus całkiem pewne cechy.

  • Metaznaki są dezaktywowane poprzez ukośnik odwrotny
  • Brak referencji
  • inaczej: wiele magicznych Wyrażeń regularnych zwykle może zrobić dla jednego

GNU Rozszerz wyrażenia regularne

dodaje następujące funkcje

Oba linki przekierują jeden do regular-expressions.info, który oprócz niesamowitego wsparcia, które tu mam, naprawdę mi bardzo pomógł.

erch
źródło