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).
Så 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).
*
eller+
i början av regex, och så görgrep -P
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.grep
(ellergrep -G
).grep -K
som använder skalmönster (där*
matchar valfritt antal tecken).*
inte är speciell när det första tecknet i en BRE, se POSIX-specifikationen