2010-02-05 12 views
9

używamWyrażenie regularne lookbehind problemem

(?<!value=\")##(.*)## 

dopasować ciąg jak ## mystring ##, że nie jest w formie:

<input type="text" value="##MyString##"> 

Działa to na powyższym formularzu, jednak nie do tego: (nadal zapałki, nie powinna zgadzać)

<input type="text" value="Here is my ##MyString## coming.."> 

próbowałem:

(?<!value=\").*##(.*)## 

bez powodzenia. Wszelkie sugestie będą głęboko docenione.

Edit: Używam preg_match() w PHP funkcji

+1

Nie używaj wyrażenia regularnego do analizy kodu HTML - użyj analizatora HTML. http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags/1732454#1732454 –

+1

Jakiego języka używasz? –

+0

Używam PHP. –

Odpowiedz

4

To nie jest doskonały (to co parser HTML są za), ale będzie pracować dla ogromnej większości plików HTML:

(^|>)[^<>]*##[^#]*##[^<>]*(<|$) 

Pomysł jest prosty. Szukasz łańcucha, który jest poza tagami. Aby znajdować się poza tagami, najbliższy poprzedzający go wspornik musi być zamknięty (lub w ogóle nie ma wspornika), a najbliższy następny musi być otwarty (lub żaden). Zakłada się, że kątowe nawiasy nie są używane w wartościach atrybutów.

Jeśli rzeczywiście obchodzi, że nazwa atrybutu jest „wartość”, a następnie można dopasować do:

value\s*=\s*"([^\"]|\\\")*##[^#]*##([^\"]|\\\")*\" 

... a potem po prostu neguje meczu (!preg_match(...)).

+0

dziękuję, to jest bardzo blisko –

0

tutaj jest punktem wyjścia przynajmniej, że pracuje dla podanych przykładów.

(?<!<[^>]*value="[^>"]*)##(.*)## 
+0

Ostrzeżenie: preg_match(): Kompilacja nie powiodła się: asercja lookbehind nie ma ustalonej długości –

+0

Nie powiedzie się z "Kompilacja nie powiodła się: asercja lookbehind nie ma ustalonej długości w offsecie 23" Używam funkcji PHP preg_match –

+0

@ Mark, myślę, że .net jest jedynym silnikiem wspierającym tego rodzaju lookbehind, o czym już wspomniałeś! Przyznaję, że problem ten jest naprawdę trudny w jakimkolwiek innym języku, mój punkt powyżej nie był skierowany specjalnie do ciebie, w rzeczywistości prawdopodobnie masz rację w tym przypadku, ale wciąż mówię, że wiele osób skacze na bandwangon bez zrozumienia. –

1

@OP, można to zrobić po prostu bez regex.

$text = '<input type="text" value=" ##MyString##">'; 
$text = str_replace(" ","",$text); 
if (strpos($text,'value="##') !==FALSE){ 
    $s = explode('value="##',$text); 
    $t = explode("##",$s[1]); 
    print "$t[0]\n"; 
} 
+0

Uważam, że w tym jest zbyt dużo kosztów ogólnych. Jeśli chodzi o zastąpienie, powiedzmy 50 ciągów, zużyje zbyt dużo zasobów. I nie zawsze są to białe spacje przed ## MyString ##, może to być cokolwiek –

+0

, jeśli jest to coś innego niż spacje przed '## Mystring ## ', to nie powinno pasować, zgodnie z własnymi kryteriami? Jeśli chodzi o koszty ogólne, nie ma sposobu, aby powiedzieć, chyba że wykonasz niektóre testy porównawcze. – ghostdog74

+0

@Dali więcej kodu nie oznacza więcej narzutów, to rozwiązanie może być nawet szybsze niż regex w niektórych sytuacjach, a wolniejsze w innych, jak mówi ghostdog74, trzeba go wypróbować. –