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).

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ør grep -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 (eller grep -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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *