Observ următorul comportament al lui grep
când îl rulez de cinci ori:
me@asus:~/go/src/company/topology-front$ lsof |grep "READ" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "README.md*" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "README.md" vim 4788 me 4u REG 8,2 12288 32247694 /home/me/go/src/company/topology-front/.README.md.swp me@asus:~/go/src/company/topology-front$ lsof |grep "*README.md*" me@asus:~/go/src/company/topology-front$ lsof |grep "*README.md" me@asus:~/go/src/company/topology-front$
Nu am putut înțelege de ce ultimele două încercări ale grep
nu returnează niciun rezultat .
Răspuns
grep
sunt expresii regulate (aka regex, regexp, RE), de bază expresii regulate (BRE) cu excepția cazului în care una dintre -E
/ -F
/ -P
/ -K
/ -X
este utilizată opțiunea (dintre care numai primele două fiind standard).
*
este un operator regexp care se potrivește cu 0 sau mai multe din atom precedent. De exemplu, d*
se potrivește cu 0 sau mai multe d
s. În BRE-uri, când se află la începutul modelului sau când se urmărește
sau \(
operatori regexp, se potrivește doar cu un literal *
(este, de asemenea, luat literalmente în interiorul [...]
expresii paranteze).
Deci grep "*README.md*"
se potrivește pe liniile care conțin un literal *
urmat de README
urmat de orice caracter unic (.
operator regexp) urmat de m
urmat de orice număr de d
. Deoarece orice număr include 0, acest lucru este „echivalent din punct de vedere funcțional cu grep "*README.m"
(ceea ce nu ar face nicio diferență cu care linii sunt potrivite, doar pe ceea ce poate fi egalat în cadrul liniei (care s-ar afișa cu opțiunea --color
a GNU grep
de exemplu)).
De exemplu , s-ar potrivi pe acele 2 rânduri:
*README mike ^^^^^^^^^ DONT***README-mddd ^^^^^^^^^^^^
(^
arată ce se potrivește în linie prin expresia regulată, pe care ați putea-o vedea cu --color
)
Aici, se pare că confundați expresiile regulate cu tiparele de caractere wildcard. *
operatorul comodin care se potrivește pe 0 sau mai multe caractere poate fi scris .*
în expresii regulate. Dar a face:
grep ".*README\.md.*"
ar fi din nou același lucru ca:
grep "README\.md"
Ca grep
caută o potrivire în linie spre deosebire de găsirea liniilor care se potrivesc exact cu modelul (pentru care aveți nevoie de -x
).
Cu ast-open grep
, care este și ksh93
„s grep
builtin (nu întotdeauna încorporat în mod implicit și trebuie să îl activați punând /opt/ast/bin
înaintea $PATH
), puteți utiliza opțiunea -K
pentru grep
pentru a folosi metacaractere shell (cele ksh93 extinse). Deci, cu acel grep
implementare, puteți face:
grep -K "README.md"
sau
grep -xK "*README.md*"
pentru a se potrivi pe liniile care conțin README.md
.
Cu aceeași implementare, potrivirea wildcard poate fi activată și în extins (), augmentat (-X
) sau perl-like (-P
) regulat expresii cu operatorul (?K)
(și \(?K\)
în expresii regulate de bază care de fapt încalcă conformitatea POSIX, așa că nu m-aș baza pe ea în timp ce poate fi eliminat într-o versiune viitoare). Deci puteți face:
grep -xE "(?K)*README.md*"
acolo.
Cu orice implementare modernă grep
, puteți face, de asemenea:
grep -F README.md
Pentru o căutare cu șir fix (unde .
de mai sus se potrivește cu un literal .
în loc de orice caracter).
*
sau+
la începutul regexului, la fel șigrep -P
grep -E
cu mai multe implementări. Acel*
tratat literal atunci când la început este specificat doar pentru BRE-uri. Cu alte RE-uri, YMMV.grep
(saugrep -G
).grep -K
care folosește modele de shell (unde*
se potrivește cu orice număr de caractere).*
nefiind special atunci când primul caracter al unui BRE, vezi specificația POSIX