Jestem nowy w wyrażeniach regularnych i byłbym wdzięczny za pomoc. Próbuję połączyć wyrażenie, które podzieli przykładowy ciąg przy użyciu wszystkich spacji, które nie są otoczone pojedynczymi lub podwójnymi cudzysłowami. Moja ostatnia próba wygląda tak: (?!")
i nie działa. Dzieli się na przestrzeni przed cytatem.
Przykładowe dane wejściowe:
This is a string that "will be" highlighted when your 'regular expression' matches something.
Pożądane wyjście:
This
is
a
string
that
will be
highlighted
when
your
regular expression
matches
something.
Zwróć na to uwagę "will be"
i 'regular expression'
zachowaj odstępy między słowami.
Odpowiedzi:
Nie rozumiem, dlaczego wszyscy inni proponują tak złożone wyrażenia regularne lub tak długi kod. Zasadniczo chcesz pobrać dwa rodzaje rzeczy ze swojego ciągu: sekwencje znaków, które nie są spacjami ani cudzysłowami, oraz sekwencje znaków, które zaczynają się i kończą cudzysłowem, bez cudzysłowów pomiędzy, dla dwóch rodzajów cudzysłowów. Możesz łatwo dopasować te rzeczy za pomocą tego wyrażenia regularnego:
Dodałem grupy przechwytywania, ponieważ nie chcesz cytatów na liście.
Ten kod Java tworzy listę, dodając grupę przechwytywania, jeśli została dopasowana, aby wykluczyć cudzysłowy, i dodając ogólne dopasowanie wyrażenia regularnego, jeśli grupa przechwytywania nie pasuje (dopasowano słowo bez cudzysłowu).
Jeśli nie masz nic przeciwko umieszczaniu cudzysłowów na zwracanej liście, możesz użyć znacznie prostszego kodu:
źródło
\"
?John's mother
wyniki podzielone[John, s, mother]
"([^"]*)"|'([^']*)'|[^\s]+
."([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|[^\s]+
. Zobacz stackoverflow.com/questions/5695240/…Istnieje kilka pytań dotyczących StackOverflow, które obejmują to samo pytanie w różnych kontekstach przy użyciu wyrażeń regularnych. Na przykład:
AKTUALIZACJA : Przykładowe wyrażenie regularne do obsługi ciągów w pojedynczych i podwójnych cudzysłowach. Ref: Jak mogę podzielić ciąg, chyba że w cudzysłowie?
Przetestowałem to za pomocą szybkiego fragmentu kodu Perl i wynik był taki, jak pokazano poniżej. Działa również dla pustych łańcuchów lub ciągów zawierających tylko białe znaki, jeśli znajdują się one w cudzysłowie (nie jestem pewien, czy jest to pożądane, czy nie).
Zauważ, że obejmuje to same znaki cudzysłowu w dopasowanych wartościach, chociaż możesz je usunąć, zastępując ciąg znaków, lub zmodyfikować wyrażenie regularne, aby ich nie uwzględniać. Zostawię to na razie jako ćwiczenie dla czytelnika lub innego plakatu, ponieważ 2 nad ranem to już zdecydowanie za późno, aby już majstrować przy wyrażeniach regularnych;)
źródło
Jeśli chcesz zezwolić na cudzysłowy w ciągu znaków, możesz użyć czegoś takiego:
Cytowane ciągi będą oznaczały grupę 2, pojedyncze słowa bez cudzysłowów będą grupą 3.
Możesz go wypróbować na różnych ciągach tutaj: http://www.fileformat.info/tool/regex.htm lub http://gskinner.com/RegExr/
źródło
Wyrażenie regularne od Jana Goyvaertsa jest najlepszym rozwiązaniem, jakie do tej pory znalazłem, ale tworzy również puste (zerowe) dopasowania, które wyklucza w swoim programie. Te puste dopasowania pojawiają się również w testerach wyrażeń regularnych (np. Rubular.com). Jeśli odwrócisz wyszukiwanie (najpierw poszukaj cytowanych części, a następnie słów oddzielonych spacjami), możesz to zrobić od razu za pomocą:
źródło
Spowoduje to dopasowanie spacji nieuwzględnionych w cudzysłowach. Muszę użyć min, max {0,99999}, ponieważ Java nie obsługuje * i + w lookbehind.
źródło
Prawdopodobnie łatwiej będzie przeszukać ciąg, chwytając każdą część, zamiast ją rozdzielać.
Powodem jest to, że możesz go podzielić na spacje przed i po
"will be"
. Ale nie mogę wymyślić żadnego sposobu, aby określić ignorowanie odstępu między wewnątrz podziału.(nie rzeczywista Java)
Ponadto przechwytywanie pojedynczych cudzysłowów może prowadzić do problemów:
źródło
String.split()
nie jest tutaj pomocne, ponieważ nie ma sposobu, aby odróżnić spacje w cudzysłowach (nie dziel) od spacji na zewnątrz (dziel).Matcher.lookingAt()
jest prawdopodobnie tym, czego potrzebujesz:co daje następujący wynik:
źródło
Podobało mi się podejście Marcusa, jednak zmodyfikowałem je, aby umożliwić umieszczanie tekstu w pobliżu cudzysłowów i obsługiwać znaki „i” cytat. Na przykład potrzebowałem a = „jakaś wartość”, aby nie dzielić go na [a =, ” jakąś wartość ”].
źródło
Podejście Jana jest świetne, ale dla przypomnienia jest jeszcze jedno.
Jeśli faktycznie chciałbyś podzielić, jak wspomniano w tytule, zachowując cudzysłowy w
"will be"
i'regular expression'
, możesz użyć tej metody, która jest prosto z Dopasuj (lub zastąp) wzorzec, z wyjątkiem sytuacji s1, s2, s3 itp.Wyrażenie regularne:
Dwie lewe alternacje są zgodne z zakończeniem
'quoted strings'
i"double-quoted strings"
. Zignorujemy te mecze. Prawa strona dopasowuje i przechwytuje spacje do grupy 1 i wiemy, że są to właściwe spacje, ponieważ nie zostały dopasowane przez wyrażenia po lewej stronie. Zastępujemy te, aSplitHere
następnie dzielimySplitHere
. Ponownie, dotyczy to prawdziwego podziału przypadku, w którym chcesz"will be"
, a niewill be
.Oto pełna działająca implementacja (zobacz wyniki w demo online ).
źródło
Jeśli używasz języka C #, możesz użyć
Specjalnie dodałem „ | <(? [\ W \ s] *)> ”, aby zaznaczyć, że możesz określić dowolny znak do wyrażenia w grupie. (W tym przypadku używam <> do grupowania.
Wynik to:
źródło
Jestem pewien, że nie jest to możliwe przy użyciu samych wyrażeń regularnych. Sprawdzanie, czy coś jest zawarte w jakimś innym tagu, jest operacją analizowania. Wydaje się, że to ten sam problem, co próba przeanalizowania XML za pomocą wyrażenia regularnego - nie można tego zrobić poprawnie. Możesz być w stanie osiągnąć pożądany rezultat, wielokrotnie stosując niechciwe, nieglobalne wyrażenie regularne, które pasuje do cytowanych ciągów, a gdy nie możesz znaleźć niczego innego, podziel je na spacje ... które ma liczbę problemy, w tym śledzenie oryginalnej kolejności wszystkich podciągów. Najlepszym rozwiązaniem jest po prostu napisanie naprawdę prostej funkcji, która iteruje po ciągu i wyciąga żądane tokeny.
źródło
Kilka, miejmy nadzieję, przydatnych poprawek w zaakceptowanej odpowiedzi Jana:
źródło
you're
Możesz też spróbować tego:
źródło
Poniższe zwraca tablicę argumentów. Argumenty to zmienna „polecenie” podzielona na spacje, chyba że są zawarte w pojedynczych lub podwójnych cudzysłowach. Dopasowania są następnie modyfikowane, aby usunąć pojedyncze i podwójne cudzysłowy.
źródło
Pierwsza jednowierszowa za pomocą String.split ()
[This, is, a, string, that, "will be", highlighted, when, your, 'regular expression', matches, something.]
nie dziel w pustym miejscu, jeśli puste miejsce jest otoczone pojedynczymi lub podwójnymi cudzysłowami,
podziel je w pustym miejscu, gdy 255 znaków po lewej i wszystkie znaki po prawej stronie nie są ani pojedynczymi, ani podwójnymi cudzysłowami
zaadaptowano z oryginalnego postu (obsługuje tylko podwójne cudzysłowy)
źródło