Как найти слово, которому предшествует другое конкретное слово?

Какому регулярному выражению, которое я могу использовать для поиска всех строк bar , не предшествует строка foo ? Наличие пробела между ними также является незаконным.

Поэтому регулярное выражение должно соответствовать следующим строкам

 foo is bar hello bar 

Но не эти

 foobar foo bar 

Я пробовал использовать следующие

 (?!<foo)bar 

и он получает работу, сделанную для устранения foobar , но мне нужно позаботиться о пробелах и, конечно же,

 (?!<foo)\s*bar 

соответствует всем строкам.

Благодаря!

Лучше использовать другие возможности языка программирования, чем выглядеть слишком сложно для шаблона регулярных выражений.

Вы ищете строки, для которых $s =~ /bar/ and not $s =~ /foo\s*bar/ истинно.

Остальная часть приведенного ниже сценария предназначена только для тестирования.

 #!/usr/bin/perl use strict; use warnings; my %strings = ( 'foo is bar' => 1, 'hello bar' => 1, 'foobar' => 0, 'foo bar' => 0, 'barbar' => 1, 'bar foo' => 1, 'foo foo' => 0, ); my @accept = grep { $strings{$_} } keys %strings; my @reject = grep { not $strings{$_} } keys %strings; for my $s ( @accept ) { if ( $s =~ /bar/ and not $s =~ /foo\s*bar/ ) { print "Good: $s\n"; } else { print "Bad : $s\n"; } } for my $s ( @reject ) { if ( $s =~ /bar/ and not $s =~ /foo\s*bar/ ) { print "Bad : $s\n"; } else { print "Good: $s\n"; } } 

Вывод:

 E: \ srv \ unur> j
 Хорошо: bar foo
 Хорошо: привет
 Хорошо: foo является баром
 Хорошо: barbar
 Хорошо: foo foo
 Хорошо: foo bar
 Хорошо: foobar

Учитывая несколько тестовых примеров

 my @match = ( "foo is bar", "hello bar", ); my @reject = ( "foobar", "foo bar", ); 

вы, конечно, можете сделать, подав результаты одного шаблона другому:

 my @control = grep !/foo\s*bar/, grep /bar/ => @match, @reject; 

Мы также можем сделать это с одним:

 my $nofoo = qr/ ( [^f] | f (?! o) | fo (?! o \s* bar) )* /x; my $pattern = qr/^ $nofoo bar /x; 

Но не верьте мне на слово.

 for (@match) { print +(/$pattern/ ? "PASS" : "FAIL"), ": $_\n"; } for (@reject) { print +(/$pattern/ ? "FAIL" : "PASS"), ": $_\n"; } 
  (?!<foo)\s*bar 

Это будет соответствовать пробелу

PHP:

 !preg_match(/foo\s*bar/,$string) && preg_match(/bar/,$string) 

Perl:

 $string !~ /foo\s*bar/ && $string =~ /bar/ 

Принимая информацию из более ранних ответов, обертывая как однострочный perl, и делая регулярные выражения без учета регистра.

Окна:

 perl -lne "print $_ if $_ !~ m/foo\s*bar/i && $_ =~ m/bar/i;" c:\temp\xx.txt 

Linux:

 perl -lne 'print $_ if $_ !~ m/foo\s*bar/i && $_ =~ m/bar/i;' /tmp/xx.txt 

С xx.txt, содержащим:

 foo is bar hello bar foobar foo bar barbar bar foo barfoo foo foo 

Результат выполнения однострочного в командной строке:

 foo is bar hello bar barbar bar foo barfoo