Ik observeer het volgende gedrag van grep
wanneer het wordt uitgevoerd vijf keer:
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$
Ik kon niet “begrijpen waarom de laatste twee pogingen van grep
geen resultaat opleveren .
Answer
grep
patronen zijn reguliere expressies (ook wel regex, regexp, RE), standaard reguliere expressies (BRE) tenzij een van -E
/ -F
/ -P
/ -K
/ -X
optie (waarvan alleen de eerste twee standaard zijn) wordt gebruikt.
*
is een regexp-operator die overeenkomt met 0 of meer van het voorgaande atoom . Bijvoorbeeld d*
komt overeen met 0 of meer d
s. In BREs, wanneer aan het begin van het patroon of wanneer de
of \(
regexp-operators, het komt overeen met een letterlijke *
alleen (deze wordt ook gebruikt letterlijk binnen [...]
expressies tussen haakjes).
Dus grep "*README.md*"
komt overeen met regels die een letterlijke *
gevolgd door README
gevolgd door een willekeurig teken (de .
regexp-operator) gevolgd door m
gevolgd door een willekeurig aantal d
s. Aangezien elk getal 0 bevat, is dat functioneel equivalent aan grep "*README.m"
(wat geen verschil zou maken aan welke regels worden gekoppeld, alleen op wat mogelijk overeenkomt binnen de regel (die zou worden weergegeven met de --color
optie van GNU grep
bijvoorbeeld)).
Bijvoorbeeld , zou het overeenkomen op die 2 regels:
*README mike ^^^^^^^^^ DONT***README-mddd ^^^^^^^^^^^^
(de ^
s laten zien wat er binnen de regel overeenkomt door de reguliere expressie, die je zou kunnen zien met --color
)
Hier lijkt het erop dat je reguliere expressies verwart met shell-jokertekens. De *
jokertekenoperator die overeenkomt met 0 of meer tekens, kan in reguliere expressies worden geschreven .*
. Maar doen:
grep ".*README\.md.*"
zou weer hetzelfde zijn als:
grep "README\.md"
Als grep
zoekt naar een overeenkomst binnen de regel in plaats van regels te vinden die exact overeenkomen met het patroon (waarvoor u -x
).
Met ast-open grep
, wat ook ksh93
“s ingebouwd (niet altijd standaard ingebouwd, en u moet het inschakelen door /opt/ast/bin
voor $PATH
), kunt u de -K
optie voor grep
gebruiken om shell-jokertekens te gebruiken (uitgebreide ksh93-tekens). Dus met die grep
implementatie, kunt u doen:
grep -K "README.md"
of
grep -xK "*README.md*"
om te matchen op regels die README.md
bevatten.
Met dezelfde implementatie kan het matchen van jokertekens ook worden ingeschakeld binnen extended (), augmented (-X
) of perl-achtig (-P
) normaal expressies met de (?K)
operator (en \(?K\)
in reguliere reguliere expressies die in feite POSIX-conformiteit verbreken, dus ik zou er niet op vertrouwen zoals kan worden verwijderd in een toekomstige versie). Dus je kunt het volgende doen:
grep -xE "(?K)*README.md*"
daar.
Met elke moderne grep
implementatie, u kunt ook het volgende doen:
grep -F README.md
Voor een zoekopdracht met een vaste tekenreeks (waarbij .
hierboven overeenkomt met een letterlijke .
in plaats van een willekeurig teken).
*
of+
aan het begin van de reguliere expressie, en dat geldt ook voorgrep -P
grep -E
met verschillende implementaties. Dat*
letterlijk behandeld aan het begin is alleen gespecificeerd voor BREs. Met andere REs, YMMV.grep
(ofgrep -G
).grep -K
die shell-patronen gebruikt (waarbij*
komt overeen met een willekeurig aantal tekens).*
niet speciaal is wanneer het eerste teken van een BRE is, zie de POSIX-specificatie