2012-07-23 16 views
14

Jak będę mógł szukać słów, których nie ma w ciągu znaków.słowa kluczowe dopasowania regex nie są w cudzysłowach

Na przykład, jeśli mam tekst:

Witam Ten tekst jest przykładem.

bla bla bla „ten tekst jest wewnątrz łańcucha”

„losowy ciąg” więcej tekstu bla bla bla „foo”

będę chciał być w stanie dopasować wszystkie słowa text że nie są w środku " ". Innymi będę chciał dopasować:

enter image description here

uwaga nie chcę, aby dopasować tekst, który jest podświetlony na czerwono, ponieważ jest wewnątrz łańcucha


Możliwe rozwiązanie:

Pracowałem nad tym i to jest to, co do tej pory miałem:

(?s)((?<q>")|text)(?(q).*?"|)

uwaga, że ​​regex używa if jako: (? (Orzeczenie) prawdziwa alternatywa | fałszywa alternatywa)

więc regex będzie czytać:

find "lub tekst. Jeśli znajdziesz "następnie wybieraj, aż znajdziesz" ponownie (. *? "), Jeśli znajdziesz tekst, a następnie nic nie rób ...

Po uruchomieniu tego wyrażenia pasuję do całego ciągu znaków. Pytanie: Wiem, że mogę usunąć wszystkie ciągi, a następnie szukać tego, czego potrzebuję.

+0

Czy wypróbowałeś generator online regex taki jak: http://txt2re.com/index-csharp.php3 – Surfbutler

+2

Dlaczego chcesz dopasować ciąg znaków, który wiesz, co to jest? Co zamierzasz zrobić z wynikiem? Intencja jest ważna dla innych, aby móc udzielić właściwej odpowiedzi. – Mithon

+0

Nie musisz znać intencji pytania, aby móc na nie odpowiedzieć. Zakładasz również, że wie, czym jest łańcuch. Daje tylko przykłady, aby pokazać, co próbuje zrobić, a niekoniecznie to, czego będzie używał w końcu. Szuka określonego wyniku i nie jest to żadna z naszych spraw, jak ten wynik ma być użyty. –

Odpowiedz

20

Oto jedna odpowiedź:

(?<=^([^"]|"[^"]*")*)text 

To znaczy:

(?<=  # preceded by... 
^   # the start of the string, then 
([^"]  # either not a quote character 
|"[^"]*" # or a full string 
)*   # as many times as you want 
) 
text  # then the text 

można łatwo rozszerzyć to obsłużyć ciągi zawierające również ucieczki.

W kodu C#:

Regex.Match("bla bla bla \"this text is inside a string\"", 
      "(?<=^([^\"]|\"[^\"]*\")*)text", RegexOptions.ExplicitCapture); 

Dodany komentarz do dyskusji - od wersji rozszerzonej (mecz na zasadzie per-line i uchwyt ucieczki). Użyj RegexOptions.Multiline na to:

(?<=^([^"\r\n]|"([^"\\\r\n]|\\.)*")*)text 

W ciąg C# to wygląda:

"(?<=^([^\"\r\n]|\"([^\"\\\\\r\n]|\\\\.)*\")*)text" 

Od teraz chcesz użyć ** zamiast " tutaj jest wersja, że:

(?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text 

Objaśnienie:

(?<=  # preceded by 
^   # start of line 
(  # either 
[^*\r\n]| # not a star or line break 
\*(?!\*)| # or a single star (star not followed by another star) 
    \*\*  # or 2 stars, followed by... 
    ([^*\\\r\n] # either: not a star or a backslash or a linebreak 
    |\\.  # or an escaped char 
    |\*(?!\*) # or a single star 
    )*   # as many times as you want 
    \*\*  # ended with 2 stars 
)*  # as many times as you want 
) 
text  # then the text 

Ponieważ ta wersja nie zawiera " znaków to czystsze w użyciu ciągiem znaków:

@"(?<=^([^*\r\n]|\*(?!\*)|\*\*([^*\\\r\n]|\\.|\*(?!\*))*\*\*)*)text" 
+0

Porges dzięki za pomoc! jeśli mam gdzie: '" \ r \ n tekst \ r \ n "bla bla ..." to nie pasuje ... Myślę, że powodem jest to, że '[^"] 'przejdzie do następnego wiersza ... –

+1

@TonoNam: Jeśli chcesz, aby dopasować na podstawie linii, a następnie zmienić zarówno "[^"] 'na" [^ "\ r \ n]' i dodać "RegexOptions.Multiline" do opcji. – porges

+0

dziękuję! To było bardzo pomocne –

5

Może to być dość trudne, ale tutaj jest jedna potencjalna metoda, która działa, upewniając się, że istnieje parzysta liczba cudzysłowów między pasującym tekstem a końcem ciągu znaków:

text(?=[^"]*(?:"[^"]*"[^"]*)*$) 

Wymień text z wyrażeniem regularnym, które chcesz dopasować.

Rubular: http://www.rubular.com/r/cut5SeWxyK

Objaśnienie:

text   # match the literal characters 'text' 
(?=    # start lookahead 
    [^"]*   # match any number of non-quote characters 
    (?:   # start non-capturing group, repeated zero or more times 
     "[^"]*"  # one quoted portion of text 
     [^"]*   # any number of non-quote characters 
    )*    # end non-capturing group 
    $    # match end of the string 
)    # end lookahead 
+0

który nie pasuje do ostatniego tekstu. Ale bardzo pomocne jest wiedzieć! +1 dzięki za pomoc. –

1

ja po prostu łapczywie dopasować tekst jest w cudzysłowach w grupie non-przechwytywania filtrować je, a następnie użyć przechwytywanie grupy do nienotowanych odpowiedzi, tak:

".*(?:text).*"|(text) 

który może chcesz udoskonalić trochę za słownych granic itp ale to powinno cię tam, gdzie chcesz iść dostać i być wyraźny czytelny próbki.

Powiązane problemy