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).
*
nebo+
na začátku regexu, stejně jakogrep -P
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.grep
(nebogrep -G
).grep -K
, který používá shell vzory (kde*
odpovídá libovolnému počtu znaků).*
není zvláštní, když je první znak BRE, viz specifikace POSIX