Při jeho spuštění pozoruji následující chování grep pětkrát:

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$ 

Nechápu, proč poslední dva pokusy grep nevracejí žádný výsledek .

Odpověď

grep vzory jsou regulární výrazy (aka regex, regexp, RE), základní regulární výrazy (BRE), pokud jeden z -E / -F / / -K / -X (pouze první dva jsou standardní).

* je operátor regexp, který odpovídá 0 nebo více předchozím atomům . Například d* odpovídá 0 nebo více d s. V BRE, když na začátku vzoru nebo při sledování

nebo \( operátory regexp, odpovídá pouze doslovnému * (je také převzato doslova uvnitř [...] výrazů v závorkách).

Takže grep "*README.md*" odpovídá řádkům, které obsahují doslovný * následovaný README následovaným libovolným jediným znakem (operátor . regexp) následovaný m následovaný libovolným počtem d s. Protože libovolné číslo zahrnuje 0, je to funkčně ekvivalentní grep "*README.m" (což by nemělo vliv na to, které řádky se shodují, pouze na tom, co se může shodovat v řádku (což by se zobrazilo například s --color možností GNU grep)).

Například , odpovídalo by to na těchto 2 řádcích:

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

(^ s ukazující, co se v řádku shoduje regulárním výrazem, který můžete vidět pomocí --color)

Zdá se, že si regulární výrazy pletete se zástupnými znaky prostředí. * operátor zástupných znaků, který odpovídá 0 nebo více znakům, lze napsat .* regulárními výrazy. Ale dělat:

grep ".*README\.md.*" 

by opět bylo stejné jako:

grep "README\.md" 

Jako grep hledá shodu uvnitř řádku, na rozdíl od hledání řádků, které přesně odpovídají vzoru (pro které potřebujete -x).

S ast-open grep, což je také ksh93 „s (ve výchozím nastavení není vždy vestavěný a musíte jej povolit tím, že /opt/ast/bin umístíte před $PATH), můžete použít -K možnost pro grep použít zástupné znaky shellu (rozšířené ksh93). Takže s tím grep implementaci můžete provést:

grep -K "README.md" 

nebo

grep -xK "*README.md*" 

shoda na řádcích, které obsahují README.md.

Se stejnou implementací lze povolit shodu se zástupnými znaky také v rámci rozšířeného (), rozšířené (-X) nebo podobné perlům (-P) výrazy s operátorem (?K) (a \(?K\) v základních regulárních výrazech, které ve skutečnosti porušují shodu POSIX, takže bych se na to nespoléhal lze v budoucí verzi odebrat). Můžete tedy:

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

tam.

S jakoukoli moderní grep implementací, můžete také udělat:

grep -F README.md 

Pro vyhledávání s pevným řetězcem (kde . výše odpovídá doslovnému . namísto libovolného znaku).

Komentáře

  • FWIW: Perl si stěžuje na * nebo + na začátku regexu, stejně jako grep -P
  • @ilkkachu , stejně tak grep -E s několika implementacemi. To * ošetřeno doslovně, když je na začátku uvedeno pouze pro BRE. S dalšími RE, YMMV.
  • @St é phaneChazelas jsem ' nenašel specifikaci přední hvězdičky . Je to někde zdokumentováno? I ' m používám prostý grep (nebo grep -G).
  • @iBug, pokud odpovíte pečlivěji, všimnete si ' čeho (myslím) ' odkazující na je pro ast-open ' s grep -K, který používá shell vzory (kde * odpovídá libovolnému počtu znaků).
  • @iBug, pokud myslíte, že * není zvláštní, když je první znak BRE, viz specifikace POSIX

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *