regexp wyszukanie w pliku stringów, ale...

0

Muszę wyszukać w pliku wszystkie wystąpienią łańcucha znaków zamkniętego w podwójny cudzysłów,
ale nie może tego łańcucha poprzedzać fraza 'Translate('.
Przykład tekstu:

Jakiś tekst i tu "string" który potrzebuję zmatchować,
a tu Translate("string2") - takiego stringa, który jest
wywołany w funkcji translate
nie chcę matchować!

?

0
Regex regex = new Regex("([^Translate(]\".*?\")");
0

Raczej:

Regex regex = new Regex("(?!Translate\\()(\"[^\"]+\")");
0

E, no mnie na Twoim wyrażeniu łapie wszystko, nawet te z Translate(.

0

@up: Pisane z palca, wiec moze jest jakis blad jeszcze, ale w Twoim sa co najmniej 2: ( bez znaku ucieczki, oraz [] oznacza 1 (sic!) znak z wymienionych, nie wszystkie.

0

Fakt, mój też jest zły. Zabieram się do poprawiania.

edit:

Regex regex = new Regex("(?<!Translate\\((\"\\w*?)*)(\".*?\")");

No, mam nadzieję, że ten będzie dobry.
Co w nim zmieniłem? Po pierwsze faktycznie użycie negacji klasy było głupie, trzeba było użyć negative lookbehind (a nie lookahead jak zrobił to johny_bravo). I generalnie sama zamiana typu lookaround byłoby wystarczające, to jednak musimy pamiętać, że jest to assercja, silnik regex zakończy sprawdzanie, gdy nie będzie pasować lookaround i nie sprawdzi nam dalej regexa. Co za tym idzie, szukanie zacznie się od kończącego (!) cudzysłowy, który będzie lecieć aż do początkowego, zgarniając wszystko po drodze. Dlatego w takiej sytuacji musimy sprawdzić czy nie jest to przypadkiem ten kończący cudzysłów, wrzucając do lookbehind całe wyrażenie aż do kończącego cudzysłowy.
Pokręciłem może trochę, ale na przykładowych danych jest w porządku.

0

kiedy wszystko inne zawiedzie, mozna uzyc dwoch prastarych metod..

  1. zamienic odrzut na dopasowanie i sprawdzic po-fakcie:

(Translate()?"([^"]*)" - $1 to nic albo 'Translate(', $2 to zlapany tekst, zakladajac ze wewnatrz stringa nikt nie escape'owal cudzyslowu.. po matchu prosty test: jesli $1 == translate to olac i szukac dalej od miejsca zakonczenia trafienia

  1. napisac z palca... klasyczna negacje ciagu..

([(]|[e](|[t]e(|[a]te(|[l]ate(|[s]late(|[n]slate(|[a]nslate(|[r]anslate(|[T]ranslate()"([^"]*)"

..negacja dosc rozbudowana zawsze wychodzi, mam nadzieje ze sie nie walnalem.. niestety, jesli silnik regex nie dostarcza operatora negacji, to trzeba sie dokaldnie w ten sposob rozpisac.. trafienie gwarantuje ze wyrazenie negowane nie wystapilo w dopasowaniu, a wiec w $1 beda 'smieci' nie bedace fraza 'Translate(', zas $2 to zlapany wyraz

mam nadzieje jednak ze w engine'ie regex .net'a jest operator negacji albo prostszy sposob na ominiecie:)

0

Dzięki Rev.pl! Twoje wyrażenie rozwiązuje problem. Przyznaje, że zrozumienie rozwiązania nie przyszło mi łatwo, choć to raptem kilka znaków :-)

Jeszcze raz dzięki i pozdro!

0

Na szczęście silnik Regexa w .NET jest bardzo rozbudowany, tzn. pozwala na umieszczanie dowolnych wyrażeń w lookbehind. Większość silników (Perl, PHP, PCRE) niestety jest na to "za głupie" ;).

@quetzalcoatl: w pewnym momencie byłem na tyle zdesperowany, że chciałem użyć tej twojej pierwszej wersji i obrobić resztę w C#, to w gruncie rzeczy pewne rozwiązanie. A drugi regex niestety nie działa - występuje problem o którym pisałem z kończącym cudzysłowem. Bardzo wątpię, że da się to zrobić bez lookbehind, a przynajmniej, żeby długość regexa nie wynosiła 300 znaków ;).

0

jesli idzie o problem z ", to szczerze, nie calkiem zrozumialem.. w kazdym badz razie, owa prastara 'negacja' czasem przy uproszczonym zapisie ma tendencje do konsumowania nadmiarowych znakow sprzed wlasciwego trafienia.. moze o to chodzilo..?

czekaj.. a co do zgarniania od konca -- przeciez [^"] blokuje przejscie przez otwierajacy..? u Ciebie bylo .+?, wiec otwierajacy " moglo tez zżerać

1 użytkowników online, w tym zalogowanych: 0, gości: 1