Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Writing a proper regular expression that handles multiple spaces

I’m struggling to write a proper regexp to use with PHP7.4 to extract required information from a string.

Here are the sample strings:

Numer właściciela: NOWAKOWSKA                                              01-234 Warsaw
Numer właściciela: NOWAK_S6_2
Numer właściciela: KOWALSKA_S6_                                            01-234 Warsaw
Numer właściciela: NOWACKI S6_                                             01-234 Warsaw

What I want to extract is accordingly:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

NOWAKOWSKA
NOWAK_S6_2
KOWALSKA_S6_
NOWACKI S6_

So far I was using the %^Numer właściciela:[[:space:]](?<owner_id>.+)$%imu which worked fine (with example from row#2). However, turns out that the other cases (#1, #3, #4) appeared during a roll-out phase and our text extraction is not accurate enough.

The problem here is with spaces, the source text may contain space inside the pattern and this space must be included in the result. However, if there are repeating spaces, they must not be included.

Tried playing around with some conditionals and negative lookaheads to exclude multiple spaces, but failed to do so.

Would really appreciate any help here.

>Solution :

In a general case, when you want to match sequences of chars separated with a single whitespace, you can use

/^Numer właściciela:\h*(?<owner_id>\S+(?:\h\S+)*)/imu

See the regex demo. \h is preferred to \s since you are extracting data from lines in a longer text, not standalone texts.

If the strings you extract are all short, you may also use

/^Numer właściciela:\h*(?<owner_id>.*?)(?:\h{2}|$)/imu

Then, it should be even more efficient, but only if they are that short as in the question. The .*? is usually as expensive as .* in strings of arbitrary length.

Pattern details:

  • ^ – start of a line (due to m flag)
  • Numer właściciela: – a literal string (replace with \h to match any horizontal whitespace)
  • \h* – zero or more horizontal whitespaces
  • (?<owner_id>\S+(?:\h\S+)*) – Group "owner_id": one or more non-whitespace chars followed with zero or more sequences of a single horizontal whitespace followed with one or more non-whitespace chars.
  • (?<owner_id>.*?)(?:\h{2}|$) – Group "owner_id" that captures any zero or more chars other than line break chars as few as possible, and then either two horizontal whitespaces or end of a line.
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading