Jeg observerer følgende opførsel af grep
når det køres fem gange:
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 sidste forsøg på grep
ikke returnerer noget resultat .
Svar
grep
mønstre er regulære udtryk (aka regex, regexp, RE), grundlæggende regulære udtryk (BRE), medmindre en af -E
/ -F
/ -P
/ -K
/ -X
-indstilling (kun de to første, hvoraf de er standard), bruges.
*
er en regexp-operator, der matcher 0 eller flere af det foregående atom . For eksempel d*
matcher 0 eller mere d
s. I BREer, når i starten af mønsteret eller når du følger
eller \(
regexp-operatorer, det matcher kun en bogstavelig *
(det er også taget bogstaveligt inde i [...]
parentesudtryk).
Så grep "*README.md*"
matcher på linjer, der indeholder en bogstavelig *
efterfulgt af README
efterfulgt af ethvert enkelt tegn (.
regexp-operatoren) efterfulgt af m
efterfulgt af et vilkårligt antal d
s. Da ethvert tal inkluderer 0, betyder det, at “funktionelt svarer til grep "*README.m"
(hvilket ikke gør nogen forskel for, hvilke linjer der matches, kun hvad der kan matches inden for linjen (som f.eks. vises med --color
-indstillingen for GNU grep
)).
For eksempel , det ville matche på disse 2 linjer:
*README mike ^^^^^^^^^ DONT***README-mddd ^^^^^^^^^^^^
(^
viser, hvad der inden for linjen er matchet ved det regulære udtryk, som du kunne se med --color
)
Her ser det ud til at du forveksler regulære udtryk med shell-wildcard-mønstre. *
jokertegnoperatøren, der matcher med 0 eller flere tegn, kan skrives .*
i regulære udtryk. Men at gøre:
grep ".*README\.md.*"
ville igen være det samme som:
grep "README\.md"
Som grep
søger et match inden for linjen i modsætning til at finde linjer, der matcher mønsteret nøjagtigt (som du har brug for -x
).
Med ast-åben grep
, hvilket også er ksh93
“s grep
builtin (ikke altid indbygget som standard, og du skal aktivere det ved at sætte /opt/ast/bin
foran $PATH
), kan du bruge indstillingen -K
til grep
til at bruge shell-wildcards (udvidede ksh93-ens). Så med det grep
implementering, du kan gøre:
grep -K "README.md"
eller
grep -xK "*README.md*"
for at matche på linjer, der indeholder README.md
.
Med den samme implementering kan jokertegnetilpasning også aktiveres inden for udvidet (), augmented (-X
) eller perl-lignende (-P
) regelmæssig udtryk med (?K)
operatoren (og \(?K\)
i grundlæggende regulære udtryk, der faktisk bryder POSIX-overensstemmelse, så jeg ville ikke stole på det, som det kunne fjernes i en fremtidig version). Så du kan gøre:
grep -xE "(?K)*README.md*"
der.
Med enhver moderne grep
implementering, kan du også gøre:
grep -F README.md
For en søgning med fast streng (hvor .
ovenfor matcher en bogstavelig .
i stedet for et hvilket som helst tegn).
Kommentarer
- FWIW: Perl klager over
*
eller+
i starten af regex, og det gørgrep -P
- @ilkkachu , det gør
grep -E
med flere implementeringer. At*
behandles bogstaveligt når det i starten er kun specificeret for BREer. Med andre REer, YMMV. - @St é phaneChazelas Jeg fandt ' ikke specifikationen for den førende stjerne . Er det dokumenteret hvor som helst? Jeg ' m bruger også
grep
(ellergrep -G
). - @iBug, hvis du har svaret omhyggeligt på svaret, vil du ' bemærke, hvad (jeg tror) dig ' der henvises til, er for ast-åben ' s
grep -K
som bruger skalmønstre (hvor*
matcher et hvilket som helst antal tegn). - @iBug, hvis du mener
*
ikke er speciel, når det første tegn i en BRE, se POSIX-specifikationen