Vreau să caut liniile care conțin oricare dintre următoarele caractere:
:
/
/
?
#
[
]
@
!
$
&
"
(
)
*
+
,
;
=
%
Răspuns
grep "[]:/?#@\!\$&"()*+,;=%[]"
În cadrul unei expresii între paranteze, [...]
, foarte puține caractere sunt ” special ” (doar un subset foarte mic, cum ar fi ]
, -
și ^
și cele trei combinații [=
, [:
și [.
). Când includeți ]
în [...]
, ]
trebuie să fie primul (posibil după un ^
). Am ales să pun ]
primul și [
ultimul pentru simetrie.
Singurul alt lucru de reținut este că un singur șir citat nu poate include un singur ghilimel, așa că folosim ghilimele duble în jurul expresiei. Întrucât folosim un șir de citate duble, coaja se va arunca în ea pentru ca lucrurile să se extindă. Din acest motiv, scăpăm de $
ca \$
ceea ce va face ca shell-ul să dea un literal $
la grep
și scăpăm de !
ca și \!
de vreme ce este o istorie expansiune în bash
(numai în shell-urile interactive bash
).
Ați dori să includeți o bară inversă în set, ar trebui să-l scăpați ca \\
, astfel încât shell-ul să ofere o singură bară inversă către grep
. De asemenea, dacă doriți să includeți un backtick `
, de asemenea, trebuie scăpat ca \`
întrucât altfel pornește o înlocuire a comenzii.
Comanda de mai sus ar extrage orice linie care conținea cel puțin unul dintre caracterele din expresia paranteză.
Folosind un șir citat simplu în loc de un șir citat dublu, care obține cele mai multe supărări cu ce caractere interpretează shell-ul:
grep "[]:/?#@!$&"""""()*+,;=%[]"
Aici, singurul lucru de reținut, în afară de plasarea ]
, este că un singur șir citat nu poate include un singur ghilimel, deci folosim în schimb o concatenare de trei șiruri:
-
"[]:/?#@!$&"
-
"""
-
"()*+,;=%[]"
O altă abordare ar fi utilizarea clasei de caractere POSIX [[:punct:]]
. Aceasta se potrivește cu un singur caracter din setul !"#$%&"()*+,-./:;<=>?@[\]^_`{|}~
, care este un set mai mare decât ceea ce este dat în întrebare (conține în plus "-.<>^_`{|}~
), dar sunt toate ” caractere de punctuație ” definite de POSIX.
LC_ALL=C grep "[[:punct:]]"
Comentarii
Răspuns
Puteți utiliza clasa de caractere [:punct:]
nu vă deranjați că se potrivește și cu alte punctuații și cu caractere speciale:
grep "[[:punct:]]" file
Comentarii
-
punct
clasa de caractere (nu macro) se potrivește cu!"#$%&'()*+,-./:;<=>?@[\]^_
{|} ~ `în locația C, care este un set de caractere ușor mai mare decât ce are utilizatorul, dar poate fi suficient de bun.
Răspuns
Puteți utiliza regex complet pentru a găsi caractere speciale în interiorul parantezelor pătrate, dacă căutați un caracter care să fie un caracter special. O resursă excelentă pentru practicarea, învățarea și verificarea expresiei dvs. regulate este regex101.com .
Acesta folosește expresii regulate Perl, care pot fi utilizate cu GNU grep cu opțiunea -P
:
grep -P "(\:|\/|\?|\#|\@|\!|\\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])" ^^^
Rețineți că aveți nevoie de doi backsl cenușă în fața semnului de dolar, deoarece are o semnificație specială în coajă, iar prima bară inversă o va scăpa pentru coajă. (Cu o singură bară inversă în față, shell-ul ar elimina bară inversă, grep
ar vedea un semn de dolar fără scăpare care înseamnă sfârșitul liniei și se potrivește cu orice linie de intrare.)
Dacă terminalul dvs. acceptă culori, aruncați și culori,
grep --color=auto -P "(\:|\/|\?|\#|\@|\!|\\$|\&|\"|\(|\)|\*|\+|\,|\;|\=|\%|\[|\])"
Iată explicația regexului meu de la 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)
Comentarii
- Nu, cu ERE standard, nu puteți ‘ să scăpați de închidere
]
cu bară inversă. bară inversă nu este specială în expresiile paranteze. Pentru a avea un]
în interiorul unei expresii între paranteze, trebuie să fie primul:[]other]
, nu[ot\]her]
. Acel ‘ este diferit de PCRE-urile pe care regex101 le descrie în mod implicit. - Ar funcționa cu
pcregrep
sau GNUgrep -P
, totuși. Și într-un anumit sens, comportamentul Perl este mai simplu: o bară inversă face întotdeauna un caracter special normal. - Corectat la -P, îmi pare rău, am amestecat -E și -P
$
acolo! Mulțumesc!bash: !\: event not found
.bash
! 🙂 Scapă și de!
… Nefiind unbash
utilizator Am uitat de asta. Voi actualiza …"[\!]"
se extinde la[\!]
chiar și atunci când extinderea istoricului este activată, deci s-ar potrivi cu o bară inversă. ‘ ai nevoie de ghilimele simple sau folosind\!
de ghilimele.bash
,zsh
are, de asemenea, acea caracteristică enervantă moștenită de la csh. în csh,!
special în interiorul'...'
și, de asemenea, atunci când nu este interactiv. Cu toate acestea, încsh
(spre deosebire de bash sau zsh), utilizarea"\!"
ar funcționa aici (bara inversă este eliminată).