user304539 user304539 - 2 months ago 15
Linux Question

Negate part of regex

I'm looking for a way to match (pseudo code)

grep -E '^[aoueiy]*(!sch|s|z)+.*$'


where
!
is no match

It should match
sabc
,
zabc
and
as
, but not
usch
.

How can I write this in a proper way with grep?

Answer

You can do it in two steps with grep -E:

grep -E '^[aeiouy]*(s|z)+' infile | grep -vE '^[aeiouy]*(sch)+'

The first pass gets all the desired matches plus the undesired, usch style matches; the second pass removes the undesired ones.

For an input file containing

sabc
zabc
as
usch

the output is

$ grep -E '^[aeiouy]*(s|z)+' infile | grep -vE '^[aeiouy]*(sch)+'
sabc
zabc
as

Or, building on redneb's answer, using grep -P and a negative look-ahead:

$ grep -P '^[aeiouy]*(?!sch)(s|z)+' infile
sabc
zabc
as