Jeg observerer følgende oppførsel av grep
når du kjører den fem ganger:
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$
Jeg kunne ikke forstå hvorfor de to siste forsøkene med grep
ikke gir noe resultat .
Svar
grep
mønstre er vanlige uttrykk (aka regex, regexp, RE), grunnleggende regulære uttrykk (BRE) med mindre en av -E
/ -F
/ -P
/ -K
/ -X
alternativet (bare de to første som er standard) brukes.
*
er en regexp-operator som samsvarer med 0 eller flere av forrige atom . For eksempel d*
samsvarer med 0 eller flere d
s. I BRE, når du begynner på mønsteret eller når du følger
eller \(
regexp-operatører, den samsvarer med en bokstavelig *
(den er også tatt bokstavelig talt i [...]
parentesuttrykk).
Så grep "*README.md*"
samsvarer med linjer som inneholder en bokstavelig *
etterfulgt av README
etterfulgt av et enkelt tegn (.
regexp-operatøren) etterfulgt av m
etterfulgt av et hvilket som helst antall d
s. Siden et hvilket som helst tall inkluderer 0, betyr det at «s funksjonelt tilsvarer grep "*README.m"
(noe som ikke gjør noen forskjell for hvilke linjer som blir matchet, bare på det som kan matches. innenfor linjen (som vises med --color
alternativet til GNU grep
for eksempel)).
For eksempel , ville det matche på de to linjene:
*README mike ^^^^^^^^^ DONT***README-mddd ^^^^^^^^^^^^
(^
viser hva innenfor linjen samsvarer av det regulære uttrykket, som du kunne se med --color
)
Her ser det ut til at du forveksler vanlige uttrykk med skall-jokertegnmønstre. *
jokertegnoperatøren som samsvarer med 0 eller flere tegn, kan skrives .*
i vanlige uttrykk. Men å gjøre:
grep ".*README\.md.*"
ville igjen være det samme som:
grep "README\.md"
Som grep
ser etter et samsvar innenfor linjen i motsetning til å finne linjer som samsvarer med mønsteret nøyaktig (som du trenger -x
).
Med ast-åpen grep
, som også er ksh93
«s grep
innebygd (ikke alltid innebygd som standard, og du må aktivere det ved å sette /opt/ast/bin
foran $PATH
), kan du bruke -K
-alternativet for grep
til å bruke shell-jokertegn (utvidede ksh93-ens). Så med det «abd75beda0″>
implementering, du kan gjøre:
grep -K "README.md"
eller
grep -xK "*README.md*"
for å matche på linjer som inneholder README.md
.
Med den samme implementeringen kan jokertegnetilpasning også aktiveres innen utvidet (), augmented (-X
) eller perl-lignende (-P
) uttrykk med operatøren (?K)
(og \(?K\)
i grunnleggende regulære uttrykk som faktisk bryter POSIX-samsvar, så jeg vil ikke stole på det som det kan fjernes i en fremtidig versjon). Så du kan gjøre:
grep -xE "(?K)*README.md*"
der.
Med enhver moderne grep
implementering, du kan også gjøre:
grep -F README.md
For et fast strengesøk (der .
ovenfor samsvarer med en bokstavelig .
i stedet for hvilket som helst tegn).
*
eller+
i starten av regex, og det gjørgrep -P
grep -E
med flere implementeringer. At*
behandles bokstavelig når i begynnelsen, er bare spesifisert for BRE. Med andre RE-er, YMMV.grep
(ellergrep -G
) også.grep -K
som bruker skallmønstre (der*
samsvarer med et hvilket som helst antall tegn).*
ikke er spesiell når det første tegnet i en BRE, se POSIX-spesifikasjonen