2016-02-06 7 views
5

Mam następujący tekst:Dlaczego to miejsce regularnego wyrębu w ostatnim dopasowaniu?

2 HCl + 12 Na + 3 (Na₃Cl₂)₂₄ → 2 NaCl + H₂

chciałbym aby dopasować każdą cząsteczkę, w tym jego współczynnik. Poniższe wyrażenie prawie działa, ale znak spacji, tuż przed ostatnim dopasowaniem, jest dopasowywany, co nie powinno. Oto regex Używam:

(([0-9]* ??\(*([a-z]+[₀-₉]*)+\)*[₀-₉]*))

Jeśli spojrzeć na ten link regex101, może łatwiej będzie zobaczyć, co mój problem jest: https://regex101.com/r/hK7jY6/1

+0

Nie widzę spacji na końcu. – Maroun

+2

jak '(((: [0-9] +) \ (* ([A-Z] + [₀-₉] *) + \) * [₀-₉] *)?)'? –

+0

@ WiktorStribiżew Tak, to zadziałało. Dzięki! Możesz to opublikować jako odpowiedź, a ja to zaakceptuję. – tobloef

Odpowiedz

5

Aktualizacja

Jeśli struny są tylko poprawnymi wzorami chemicznymi, po co zawracać sobie głowę za pomocą dolnego indeksu/cyfr/liter? Istnieją nie-białe znaki:. Ponieważ nie musi być obowiązkowa list lub (, używać ich w klasy postaci [a-z(], a następnie dołączyć \S* (zero lub więcej nie spacje):

/(?:\d+)?[a-z(]\S*/gi 

Zobacz regex demo. (?:...)? konstruktem jest opcjonalnie Grupa bez chwytania (czyli grupa, która służy tylko do grupy, nie wychwytywania (= przechowywania submatch wewnątrz bufora pamięci).

oryginalny odpowiedź z wyjaśnieniem przyczynę

masz cyfry i przestrzeni wzorca na początku jako opcjonalne podwzorów, zamiast tego, trzeba dopasować je obligatoryjnie, ale umieścić w opcjonalnym grupy:

(?:[0-9]+)?\(*([a-z]+[₀-₉]*)+\)*[₀-₉]* 

Zobacz regex demo

Twoja [0-9]* ?? zamieniła się w (?:[0-9]+)?. Zauważ, że tutaj nie musisz używać leniwa wersja kwantyfikatora ?, będzie działać tak samo jak chciwy. Usunąłem również 2 niepotrzebne zewnętrzne grupy (...).

Ponieważ grupa (?:[0-9]+)? jest opcjonalna, spacja zostanie dopasowana tylko wtedy, gdy przed nią znajduje się cyfra. Jeśli nie ma cyfry, następnym znakiem, który można dopasować, jest zero lub więcej (. Wtedy powinna być obecna litera [a-z] (jeśli nie ma (, litera będzie pierwszą postacią w meczu).

Pozwól mi rozbicie go:

  • (?:[0-9]+)? - opcjonalnie jedna lub więcej cyfr po nim spacja
  • \(* - zero lub więcej ( (może chodziło ?)
  • ([a-z]+[₀-₉]*)+ - zero lub więcej sekwencje jednego lub większej liczby liter następuje zero lub więcej cyfr sbscript
  • \)* - zero lub więcej ) (być może chodziło o ?)
  • [₀-₉]* - zero lub więcej indeksie dolnym cyfry

Jeśli chcesz również upewnić się, że nie pasują (Ca lub H), należy również podzielić \(*...\)* takiego:

(?:[0-9]+)?(?:(?:[a-z]+[₀-₉]*)+|\((?:[a-z]+[₀-₉]*)+\))[₀-₉]* 

widoczny another demo

+0

Ponieważ cała grupa jest opcjonalna, pierwsze miejsce nie jest dopasowane w przypadku H2, prawda? – Michael

+1

Dodałem więcej szczegółów, piszę na laptopie. Myślę, że wciąż możesz poprawić to wyrażenie, ale bez dokładnych wymagań, to wszystko, co mogę teraz zasugerować. Zauważ, że nadal istnieje opcjonalne '(' tam, przed literą.Nie jest pewne, że jest oczekiwane.Również '*' jest stosowane do '\ (', może po prostu chcesz '?'. –

+1

Mam nadzieję, że to wszystko teraz . Jeśli potrzebujesz regex być zgodny z ECMAScript 5 (JS), to jest wszystko, co mogę zasugerować. –

2

Podczas gdy odpowiedź Wiktora jest bardzo pouczająca, myślę, że mógłbym znaleźć łatwiejszy sposób robienia tego.

([0-9]+)*[a-z\(₀-₉\)]+

ten będzie pasował do wszystkich części równania ile mogę powiedzieć.

Demo

Aktualizacja

proszę zobaczyć aktualizacje Wiktors odpowiedzieć, że to lepsze niż to.

+1

nie trzeba było powiedzieć wstępnie zatwierdzone ciągi, a wzór sugerują, że. Jeśli nie nie wymaga żadnej wstępnej walidacji, opublikowałem inny regex, którego możesz użyć regex, nie ma potrzeby ucieczki od '(' i ')' wewnątrz klasy znaków. –

+0

Rozumiem. Prawdopodobnie powinienem to teraz skomentować. Dziękuję za pomoc, jeszcze raz. – tobloef

+0

@TobLoef nawet [tak] (https://regex101.com/r/uR7pC3/1): '\ b [\ w₀-₉) (]? + (\ S) ' –

Powiązane problemy