2008-10-28 11 views
18

Próbuję napisać wyrażenie zastępcze zastępujące wszystkie słowa w cudzysłowach za wyjątkiem wyrazów AND, OR i NOT.Regex, aby dopasować wszystkie wyrazy z wyjątkiem podanej listy

Próbowałem następujących dla części meczu wyrażenia:

(?i)(?<word>[a-z0-9]+)(?<!and|not|or) 

i

(?i)(?<word>[a-z0-9]+)(?!and|not|or) 

ale żadna praca. Zamienne wyrażenie jest proste i obecnie otacza wszystkie słowa.

"${word}" 

Więc

to i to nie to

staje

"To" i "To" nie "że"

+0

Czy możesz podać przykładowe dane wejściowe i oczekiwany wynik (dopasowanie lub nie)? – mohammedn

+0

(? I) (? [a-z0-9] ++) (?

Odpowiedz

14

ten jest trochę brudny, ale to działa:

(?<!\b(?:and| or|not))\b(?!(?:and|or|not)\b) 

W prostym języku angielskim, to słowo pasuje dowolny granica nie poprzedza i następuje po niej „i”, „lub”, lub „nie”. Dopasowuje tylko całe słowa, np. pozycja po słowie "piasek" nie byłaby zgodna tylko dlatego, że poprzedza ją "i".

Przestrzeń przed "lub" w asercji szerokości zerowej jest niezbędna, aby uzyskać stałą długość spojrzenia. Spróbuj, jeśli to już rozwiązuje twój problem.

EDYCJA: Stosowana do łańcucha "z wyjątkiem słów AND, OR i NOT." jako globalny zastąpić pojedyncze cudzysłowy, to zwraca:

'except' 'the' 'words' AND, OR and NOT. 
+0

Jedyną sytuacją, w której może to się nie powieść, jest sytuacja, w której ciąg zaczyna się od słowa "lub". Okay, i zawiera ukryte założenie, że przestrzenie oddzielają twoje słowa. Obie sytuacje można migrować, jeśli znasz swoje dane. – Tomalak

+0

Podobnie jak w przypadku wszystkich regex, jest szalony, ale działa. ( [A-Z0-9] +?) ( John

+0

Co trzeba „( [a- z0-9] +) "for? Czy próbujesz otoczyć twoje słowa cytatami, czy próbujesz je wyrwać z łańcucha? – Tomalak

3

Call me crazy, ale nie jestem fanem walki regex; Ograniczę moje wzorce do prostych rzeczy mogę zrozumieć, a często oszukują na resztę - na przykład za pośrednictwem MatchEvaluator:

string[] whitelist = new string[] { "and", "not", "or" }; 
    string input = "foo and bar or blop"; 
    string result = Regex.Replace(input, @"([a-z0-9]+)", 
     delegate(Match match) { 
      string word = match.Groups[1].Value; 
      return Array.IndexOf(whitelist, word) >= 0 
       ? word : ("\"" + word + "\""); 
     }); 

(edytowany więcej lakonicznym układu)

+1

Nazywam cię szalonym. :-P – Tomalak

+1

@Tomalak: Touché –

+0

Niestety jest to kropka netto 2, więc żadna lambda jeszcze nie – John

2

podstawie Tomalaks odpowiedź:

Ten regex ma dwa problemy:

  1. (?<!) działa tylko w przypadku ustalonej długości, za którą odpowiada tylko jeden element:

  2. W poprzednim wyglądzie uwzględniono tylko końcowy koniec/początek otaczających słów, a nie całe słowo.

(?<!\band)(?<!\bor)(?<!\bnot)\b(?!(?:and|or|not)\b)

Ten regex rozwiązuje oba powyższe problemy. Najpierw podzielcie uwagę na trzy odrębne. Po drugie, dodając granice wyrazów (\b) wewnątrz rozejrzanych widoków.

5

John,

Regex na twoje pytanie jest prawie poprawne. Jedyny problem polega na tym, że wstawiasz widok z wyprzedzeniem na końcu wyrażenia regularnego zamiast na początku. Ponadto musisz dodać granice słów, aby zmusić wyrażenie regularne do dopasowania całych słów. W przeciwnym razie będzie pasować do "nd" w "i", "r" w "lub", itp., Ponieważ "nd" i "r" nie znajdują się w negatywnej poprzedniej stronie.

\ b (i?) (I |? | Nie lub) (? [A-Z0-9] +) \ b

+0

Tak, wszyscy inni sprawiają, że jest to o wiele bardziej skomplikowane, niż powinno być. W szczególności nie ma potrzeby negatywnego (lub pozytywnego, o ile to ważne) wyglądu lub nazwanego przechwytywania. –

+0

Dwie rzeczy: po pierwsze, doszedłem do wniosku, że określenie dosłowne '[az]' w wyrażeniu regularnym zamiast '\ pL' lub' \ p {alfabetycznie} 'lub czasami' [[: alfa:]] ' jest prawie zawsze zbyt "1960" w naszym wieku po 7-bit. Po drugie, znajduję ludzi [często źle rozumieją to, co \ b naprawdę robi] (http://stackoverflow.com/questions/4213800/to-there-something-like-a-counter-variable-in-regular-expression-replace/4214173 # 4214173), więc ostatnio dodawałem zastrzeżenia do jego gotcha za każdym razem, gdy go polecam. (Tak, wiem, że * ty * oczywiście rozumiesz to wszystko, Jan, ale wielu czytelników prawdopodobnie tego nie robi.) – tchrist

0
(?!\bnot\b|\band\b|\bor\b|\b\"[^"]+\"\b)((?<=\s|\-|\(|^)[^\"\s\()]+(?=\s|\*|\)|$)) 

Używam tego regex znaleźć wszystko słowa, które nie znajdują się w podwójnych cudzysłowach lub są słowami "nie" i "lub" lub ".

Powiązane problemy