可以使用哪個正則表達式來查找所有字符串bar
前面沒有字符串foo
?兩者之間有空白也是非法的。如何找到一個單詞之前沒有另一個特定的單詞?
所以,正則表達式應該採用以下
(?!<foo)bar
符合下列字符串
foo is bar
hello bar
但不是這些
foobar
foo bar
我試着和它得到所做的工作消除foobar
,但我需要照顧的空白,當然
(?!<foo)\s*bar
匹配所有字符串。
謝謝!
可以使用哪個正則表達式來查找所有字符串bar
前面沒有字符串foo
?兩者之間有空白也是非法的。如何找到一個單詞之前沒有另一個特定的單詞?
所以,正則表達式應該採用以下
(?!<foo)bar
符合下列字符串
foo is bar
hello bar
但不是這些
foobar
foo bar
我試着和它得到所做的工作消除foobar
,但我需要照顧的空白,當然
(?!<foo)\s*bar
匹配所有字符串。
謝謝!
(?!<foo)\s*bar
這將匹配空白
呃沒有。首先,它是'(?<!..)',其次,'\ s *'需要在lookbehind內部,否則它總是匹配,除非'foo'和'bar'之間沒有空格。馬克·拜爾斯說得對。 – 2009-12-02 21:43:45
確定我所知道的是JA編輯我的答案,我感到有福。 – Hogan 2009-12-03 16:28:40
PHP:
!preg_match(/foo\s*bar/,$string) && preg_match(/bar/,$string)
的Perl:
$string !~ /foo\s*bar/ && $string =~ /bar/
正如原始問題中提到的,這不起作用。 – Sleepster 2009-12-02 20:49:54
嗯,是的,因爲所有的字符串在技術上都可以被發現在非酒吧串之前... – 2009-12-02 20:56:45
你真正需要的是做一個負面的正則表達式。 $ string!〜/ foo \ s * bar /。用php和perl版本更新。 – 2009-12-02 21:02:30
鑑於一些測試用例
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";
}
令人印象深刻的是,你得到了這個工作。最有可能的「富」和「酒吧」只是更長的字符串的佔位符。看起來你的正則表達式對於任何真實世界的例子都會變得非常長。儘管爲不同的方法+1。 – 2009-12-02 23:28:17
謝謝,可悲的消息是字面模式是最好的情況。我想知道這種方法的侷限性是什麼。對於這樣的任務來說,有一個正則表達式開關可以補充每個NFA狀態的接受狀態。 – 2009-12-03 19:54:26
更好地使用編程語言的其他工具,而不是看看太正確的正則表達式模式。
您在查找$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 Good: bar foo Good: hello bar Good: foo is bar Good: barbar Good: foo foo Good: foo bar Good: foobar
即使字符串不包含「酒吧」,這不會匹配嗎? – 2009-12-02 21:26:02
@Mark Byers:謝謝你指出我的疏忽。固定。 – 2009-12-02 21:51:22
'酒吧foobar'也使一個有趣的測試案例。雖然我不確定預期的輸出是什麼。 – 2009-12-02 22:30:15
以從早期的答案信息,包裝作爲一個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
「匹配所有字符串」。 - 迂迴模式:(?!
2009-12-02 20:54:35
您說得對,謝謝指出! 我結束了使用以下內容: preg_match('/(foo)?\ s * bar /',haystack,matches); 這將找到酒吧(無論前面是否有foo),然後對匹配[]進行快速檢查將確定foo是否存在。 – Sleepster 2009-12-03 00:34:25
您正在尋找的東西具體稱爲**零寬度負面後顧斷言**。 Perl顯然不支持可變寬度後視(正面或負面),所以像\ s *之類的東西在其中一個將不起作用。嘗試使用多個匹配運算符。 – fennec 2009-12-30 05:25:54