in reply to Seeker of Regex Wisdom (strings which don't form specific patterns)
... a regex for grep -P that would show me lines which had, roughly, ^[one or more non-whitespace chars, which also do not form an IP address][one or more whitespace chars][zero or more chars][an IP address]
My 0.02USD. It's possible to rigorously express all the stated requirements as regexes. It's highly convenient to do so by building upon existing Perl modules such as Regexp::Common.
The requirement
[one or more non-whitespace chars, which also do not form an IP address]
can be exactly expressed as
my $S_not_IPv4 = qr{ (?! $RE{net}{IPv4}) \S }xms
for a single such character, and
$S_not_IPv4+
(within a regex) as "one or more" such characters.
The requirements [one or more whitespace chars] and [zero or more chars] are exactly met by \s+ and .* respectively.
For
[an IP address]
it's convenient to use $RE{net}{IPv4} defined in Regexp::Common::net, but this regex has a subtlety: it intentionally does not include boundary conditions and so may match what might be considered a non-IPv4 string in certain circumstances:
The programmer must determine the proper match criteria for each circumstance. I have used a "loose" criterion in the $S_not_IPv4 definition, and also have a tighter $ip definition that would exclude the '54321.2.3.45678' match above.c:\@Work\Perl\monks>perl -wMstrict -le "use Regexp::Common qw(net); ;; print 'match' if '54321.2.3.45678' =~ m{ $RE{net}{IPv4} }xms; " match
So finally:
It's a bit wordy, but still possible to express as a CLI one-liner. I think it can be said to exactly meet the stated requirements. It does so in Perl and not for grep, but that's life.c:\@Work\Perl\monks>perl -wMstrict -le "use Regexp::Common qw(net); ;; my $ip = qr{ (?<! \d) $RE{net}{IPv4} (?! \d) }xms; my $S_not_IPv4 = qr{ (?! $RE{net}{IPv4}) \S }xms; ;; for my $s ( 'ADMIN__SANDRO_DESK=\"123.45.78.90\" # ilcylic Desktop', '# ADMIN__SANDRO_DESK=\"123.45.78.91\" # ilcylic Desktop (old)', '# 06/06/15 SR Chgd SANDRO 121.123.65.92', @ARGV, ) { my $match = $s =~ m{ \A $S_not_IPv4+ \s+ .* $ip }xms; printf qq{%8s '%s' \n}, $match ? 'MATCH' : 'no match', $s; } " no match 'ADMIN__SANDRO_DESK="123.45.78.90" # ilcylic Desktop' MATCH '# ADMIN__SANDRO_DESK="123.45.78.91" # ilcylic Desktop (ol +d)' MATCH '# 06/06/15 SR Chgd SANDRO 121.123.65.92'
Give a man a fish: <%-(-(-(-<
|
|---|