Regex, jak dopasować opcjonalny znak

147

Mam wyrażenie regularne, o którym sądziłem, że do tej pory działa poprawnie. Muszę dopasować opcjonalną postać. Może tam być lub nie.

Oto dwie struny. Górna struna jest dopasowana, a dolna nie. Brak pojedynczej litery w dolnym łańcuchu jest przyczyną niepowodzenia.

Chciałbym uzyskać pojedynczą literę po pierwszych 5 cyfrach, jeśli tam jest, a jeśli nie, kontynuuj pobieranie pozostałej części ciągu. Ten list może być A-Z.

Jeśli usunę ([A-Z]{1}) +.*? +z wyrażenia regularnego, będzie pasować do wszystkiego, czego potrzebuję, z wyjątkiem litery, ale jest to dość ważne.

20000      K               Q511195DREWBT            E00078748521
30000                      K601220PLOPOH            Z00054878524

Oto wyrażenie regularne, którego używam.

/^([0-9]{5})+.*? ([A-Z]{1}) +.*? +([A-Z]{1})([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3}) +([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})/
jim
źródło

Odpowiedzi:

246

Posługiwać się

[A-Z]?

aby list był opcjonalny. {1}jest zbędny. (Oczywiście możesz też napisać, [A-Z]{0,1}co oznaczałoby to samo, ale po to ?służy.)

Możesz poprawić swoje wyrażenie regularne do

^([0-9]{5})+\s+([A-Z]?)\s+([A-Z])([0-9]{3})([0-9]{3})([A-Z]{3})([A-Z]{3})\s+([A-Z])[0-9]{3}([0-9]{4})([0-9]{2})([0-9]{2})

A ponieważ w większości dialektów wyrażeń regularnych \djest to to samo, co [0-9]:

^(\d{5})+\s+([A-Z]?)\s+([A-Z])(\d{3})(\d{3})([A-Z]{3})([A-Z]{3})\s+([A-Z])\d{3}(\d{4})(\d{2})(\d{2})

Ale: czy naprawdę potrzebujesz 11 oddzielnych grup przechwytywania? A jeśli tak, dlaczego nie uchwycisz czwartej do ostatniej grupy cyfr?

Tim Pietzcker
źródło
Tim, szczerze nie jestem pewien, ponieważ nie napisałem tego wyrażenia regularnego. Wciąż jestem całkiem nowy w regex. Jeśli widzisz lepszy sposób pisania tego, jestem otwarty na sugestie.
jim
1
Tim, twój przykład działa dla obu łańcuchów, niezależnie od tego, czy mam literę na tej pozycji, czy nie. Dzięki.
jim
26

Możesz ustawić pojedynczą literę jako opcjonalną, dodając ?po niej jako:

([A-Z]{1}?)

Kwantyfikator {1}jest zbędny, więc możesz go porzucić.

codaddict
źródło
Dzięki codeaddict. Czy znak zapytania zastępuje znak `+. *? + `?
jim
Używając grep regex, otrzymasz błąd, jeśli usuniesz {1} (asercja grep: lookbehind nie ma stałej długości). Więc to jest
powód
6

Musisz również oznaczyć pojedynczą literę jako opcjonalną:

([A-Z]{1})? +.*? +

lub uczyń całą część opcjonalną

(([A-Z]{1}) +.*? +)?
Stefan
źródło
1
Stefan, chciałbym, aby list był całkowicie opcjonalny. Próbowałem obu z nich, ale nadal nic nie pasuje. Jestem pewien, że źle to zrozumiałem. Czy możesz zmodyfikować swój przykład, aby uwzględnić go w ciągu?
jim
0

Możesz także użyć prostszego wyrażenia regularnego zaprojektowanego dla twojego przypadku, na przykład (.*)\/(([^\?\n\r])*)gdzie $2pasuje do tego, co chcesz.

robinvrd
źródło