Chcę wyszukać wiersze zawierające dowolny z następujących znaków:

: / / ? # [ ] @ ! $ & " ( ) * + , ; = %

Odpowiedź

grep "[]:/?#@\!\$&"()*+,;=%[]" 

W wyrażeniu w nawiasach kwadratowych, [...], jest bardzo mało znaków ” specjalny ” (tylko bardzo mały podzbiór, na przykład ], - i ^ oraz trzy kombinacje [=, [: i [.). Włączając ] do [...], ] musi znajdować się na pierwszym miejscu (prawdopodobnie po ^). Zdecydowałem się umieścić ] jako pierwsze, a [ na końcu dla symetrii.

Jedyną inną rzeczą do zapamiętania jest że pojedynczy cudzysłów nie może zawierać pojedynczego cudzysłowu, więc używamy podwójnych cudzysłowów wokół wyrażenia. Ponieważ używamy łańcucha w podwójnych cudzysłowach, powłoka będzie w nim przeszukiwać, aby coś się rozszerzyć. Z tego powodu pomijamy $ jako \$, co spowoduje, że powłoka nada literał $ do grep i uciekamy z ! jako \!, bo to też historia rozwijanie w bash (choć tylko w interaktywnych bash powłokach).

Czy chcesz dołączyć ukośnik odwrotny do ustaw, musisz zmienić jego znaczenie jako \\, tak aby powłoka nadała pojedynczy ukośnik odwrotny do grep. Ponadto, jeśli chcesz uwzględnić odwrotny znacznik `, również musi być zapisany jako \`, ponieważ w przeciwnym razie rozpoczyna zastępowanie polecenia.

Polecenie powyżej wyodrębniłby każdy wiersz, który zawierał co najmniej jeden ze znaków w wyrażeniu w nawiasach.


Użycie pojedynczego cudzysłowu zamiast podwójnego cudzysłowu, co pozwala obejść większość niedogodności jakie znaki interpretuje powłoka:

grep "[]:/?#@!$&"""""()*+,;=%[]" 

Tutaj jedyna rzecz do zapamiętania oprócz umieszczenia ] jest taki, że pojedynczy cytowany ciąg nie może zawierać pojedynczego cudzysłowu, więc zamiast tego używamy konkatenacji trzech ciągów:

  1. "[]:/?#@!$&"
  2. """
  3. "()*+,;=%[]"

Innym podejściem byłoby użycie klasy znaków POSIX [[:punct:]]. Dopasowuje pojedynczy znak ze zbioru !"#$%&"()*+,-./:;<=>?@[\]^_`{|}~, który jest większym zestawem niż to, co podano w pytaniu (dodatkowo zawiera "-.<>^_`{|}~), ale to wszystkie ” znaki interpunkcyjne „, które definiuje POSIX.

LC_ALL=C grep "[[:punct:]]" 

Komentarze

  • @ilkkachu Nie ' nie zauważyłem $ tam! Dzięki!
  • Kiedy próbuję wykonać polecenie, pojawia się ten błąd bash: !\: event not found.
  • @ user9371654 Cholera bash! 🙂 Ucieknij z ! też … Nie będąc bash użytkownik Zapomniałem o tym. Zaktualizuję …
  • "[\!]" rozwija się do [\!] nawet jeśli włączone jest rozwijanie historii, więc będzie pasować po odwrotnym ukośniku. ' d potrzebujesz pojedynczych cudzysłowów lub użyj \! outsi de of quotes.
  • Zwróć uwagę, że ' to nie tylko bash, zsh ma również tę irytującą funkcję odziedziczoną z csh. w csh, ! specjalne wewnątrz '...', a także gdy nie jest interaktywne. Jednak w csh (w przeciwieństwie do bash lub zsh), użycie "\!" będzie działać tutaj (ukośnik odwrotny jest usuwany).

Odpowiedź

Możesz użyć klasy znaków [:punct:], jeśli nie ważne, że pasuje również do innych znaków interpunkcyjnych i specjalnych:

grep "[[:punct:]]" file 

Komentarze

  • punct klasa znaków (nie makro) pasuje do !"#$%&'()*+,-./:;<=>?@[\]^_ {|} ~ `w języku C, który jest nieco większym zestawem znaków niż co ma użytkownik, ale może być wystarczająco dobre.

Odpowiedź

Możesz użyć pełnego wyrażenia regularnego, aby znaleźć znaki specjalne w nawiasach kwadratowych, jeśli szukasz jednego znaku, który jest znakiem specjalnym. Świetnym źródłem ćwiczenia, nauki i sprawdzania wyrażeń regularnych jest regex101.com .

Używa wyrażeń regularnych Perla, których można używać z GNU grep z opcją -P:

grep -P "(\:|\/|\?|\#|\@|\!|\\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])" ^^^ 

Zauważ, że potrzebujesz dwóch backsl popiół przed znakiem dolara, ponieważ ma on specjalne znaczenie w powłoce, a pierwszy lewy ukośnik zostanie usunięty z powłoki. (Z tylko jednym ukośnikiem odwrotnym na początku, powłoka usuwałaby ukośnik odwrotny, grep widziałby znak dolara bez znaku zmiany znaczenia oznaczający koniec wiersza i pasowałby do dowolnego wiersza wprowadzania.)

Jeśli twój terminal obsługuje kolory, włącz również kolory,

grep --color=auto -P "(\:|\/|\?|\#|\@|\!|\\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])" 

Oto wyjaśnienie mojego wyrażenia regularnego z regex101.com

/(\:|\/|\?|\#|\@|\!|\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])/gm 1st Capturing Group (\:|\/|\?|\#|\@|\!|\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\]) \: matches the character : literally (case sensitive) \/ matches the character / literally (case sensitive) \? matches the character ? literally (case sensitive) \# matches the character # literally (case sensitive) \@ matches the character @ literally (case sensitive) \! matches the character ! literally (case sensitive) \$ matches the character $ literally (case sensitive) \& matches the character & literally (case sensitive) \" matches the character " literally (case sensitive) \( matches the character ( literally (case sensitive) \) matches the character ) literally (case sensitive) \* matches the character * literally (case sensitive) \+ matches the character + literally (case sensitive) \, matches the character , literally (case sensitive) \; matches the character ; literally (case sensitive) \= matches the character = literally (case sensitive) \% matches the character % literally (case sensitive) \[ matches the character [ literally (case sensitive) \] matches the character ] literally (case sensitive) 

Komentarze

  • Nie, w przypadku standardowego ERE nie można ' ominąć zamykającego ] z odwrotnym ukośnikiem. ukośnik odwrotny nie jest specjalnym wyrażeniem w nawiasach. Aby ] wewnątrz wyrażenia nawiasowego, musi znajdować się jako pierwsze: []other], a nie [ot\]her]. To ' różni się od PCRE, które domyślnie opisują wyrażenie regularne.
  • Będzie działać z pcregrep lub GNU grep -P, chociaż. I w pewnym sensie zachowanie Perla jest prostsze: odwrotny ukośnik zawsze sprawia, że znak specjalny jest normalny.
  • Poprawiono na -P, przepraszam za to, pomieszano -E i -P

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *