Jag observerar följande beteende för grep när du kör det fem gånger:

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$ 

Jag kunde inte förstå varför de två sista försöken av grep inte ger något resultat .

Svar

grep mönster är reguljära uttryck (aka regex, regexp, RE), grundläggande reguljära uttryck (BRE) såvida inte en av -E / -F / -P / -K / -X alternativet (endast de två första som är standard) används.

* är en regexp-operator som matchar 0 eller fler av föregående atom . Till exempel d* matchar 0 eller mer d s. I BRE, när i början av mönstret eller när du följer

eller \( regexp-operatörer, det matchar endast en bokstavlig * (det tas också bokstavligen inuti [...] parentesuttryck).

grep "*README.md*" matchar på rader som innehåller en bokstavlig * följt av README följt av ett enskilt tecken (. regexp-operatören) följt av m följt av valfritt antal d s. Eftersom vilket nummer som helst inkluderar 0, är det ”funktionellt ekvivalent med grep "*README.m" (vilket inte skulle göra någon skillnad för vilka rader som matchas, bara vad som kan matchas inom raden (som skulle visas med --color alternativet för GNU grep till exempel)).

Till exempel , det skulle matcha på de två raderna:

*README mike ^^^^^^^^^ DONT***README-mddd ^^^^^^^^^^^^ 

(^ visar vad inom raden matchas av det reguljära uttrycket, som du kunde se med --color)

Här verkar det som om du förvirrar vanliga uttryck med skal-jokerteckenmönster. * jokerteckenoperatören som matchar på 0 eller fler tecken kan skrivas .* i reguljära uttryck. Men att göra:

grep ".*README\.md.*" 

skulle återigen vara detsamma som:

grep "README\.md" 

Som grep letar efter en matchning inom raden i motsats till att hitta rader som matchar mönstret exakt (för vilket du behöver -x).

Med en öppen grep, vilket också är ksh93 ”s grep inbyggt (inte alltid inbyggt som standard, och du måste aktivera det genom att sätta /opt/ast/bin före $PATH), du kan använda alternativet -K för grep för att använda skal-jokertecken (utökade ksh93-sådana). Så med det grep implementering kan du göra:

grep -K "README.md" 

eller

grep -xK "*README.md*" 

för att matcha på rader som innehåller README.md.

Med samma implementering kan jokerteckenmatchning också aktiveras inom utökat (), augmented (-X) eller perl-liknande (-P) uttryck med (?K) operatören (och \(?K\) i grundläggande reguljära uttryck som faktiskt bryter POSIX-överensstämmelse, så jag skulle inte lita på det som det kan tas bort i en framtida version). Så du kan göra:

grep -xE "(?K)*README.md*" 

där.

Med alla moderna grep implementeringar, Du kan också göra:

grep -F README.md 

För en fast strängsökning (där . ovan matchar en bokstavlig . istället för vilket tecken som helst).

Kommentarer

  • FWIW: Perl klagar över * eller + i början av regex, och så gör grep -P
  • @ilkkachu , så gör grep -E med flera implementeringar. Att * behandlas bokstavligen när det är i början är bara specificerat för BRE. Med andra RE, YMMV.
  • @St é phaneChazelas Jag hittade ' inte specifikationen för den ledande asterisken . Är det dokumenterat någonstans? Jag ' använder också grep (eller grep -G).
  • @iBug, om du ändrar svaret mer noggrant, så ' kommer att märka vad (jag tror) du ' hänvisar till är för ast-öppen ' s grep -K som använder skalmönster (där * matchar valfritt antal tecken).
  • @iBug, om du menar * inte är speciell när det första tecknet i en BRE, se POSIX-specifikationen

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *