ShockKhay
ShockKhay

Reputation: 75

Regex for validation of coordinates (latitude and longitude pairs) array in a string

I need a REGEX expression for validating a string which looks like this:

latitude,longitude|latitude,longitude|... (n of these pairs) ...|latitude,longitude

Now, I have REGEX for latitude which is:

/^(-?[1-8]?\d(?:\.\d{1,18})?|90(?:\.0{1,18})?)$/

and a regex for longitude which is:

/^(-?(?:1[0-7]|[1-9])?\d(?:\.\d{1,18})?|180(?:\.0{1,18})?)$/

Since I don't understand or have ever done REGEX expressions, I'm begging someone experienced in this to provide with an expression that will validate my string.

I'm using this in PHP, Laravel 4.2 to be specific. But, I'm guessing the solution to this would work in Javascript as well.

Upvotes: 2

Views: 3378

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626738

It is a bad idea to use regexps of such complexity if you do not know regex well. Especially if you need to use it in both JS and PHP.

I suggest using this technique:

  • declare variables (blocks) for both longitude and latitude
  • compile a regex with required syntax using those blocks.

So, (in JS) you blocks are

var latitude = "(-?[1-8]?\\d(?:\\.\\d{1,18})?|90(?:\\.0{1,18})?)";
var longitude = "(-?(?:1[0-7]|[1-9])?\\d(?:\\.\\d{1,18})?|180(?:\\.0{1,18})?)";

The "wrapper" expression will be

var regex_str = "^(?:" + latitude + "," + longitude + "(?:\\|(?:" + latitude + "," + longitude + "))*$";

A few notes on this:

  • ^ - start of string anchor (only match the next subpattern if it is the first symbol(s) in the input string)
  • (?:...) - non-capturing groups that are only grouping, not capturing (that is, not storing any matched substrings in any buffer)
  • \\| - matches a literal | symbol (must be escaped)
  • * - a quantifier meaning 0 or more occurrences of the preceding subpattern (class, group, etc.)

I double-escape the backslashes as in JS you'd need a constructor to initialize the regex build dynamically (var rx = RegExp(regex_str)). In PHP, you can use $rx = "/$regex_str/".

The whole regex will look like

/^(?:(-?[1-8]?\d(?:\.\d{1,18})?|90(?:\.0{1,18})?),(-?(?:1[0-7]|[1-9])?\d(?:\.\d{1,18})?|180(?:\.0{1,18})?))(?:\|(?:(-?[1-8]?\d(?:\.\d{1,18})?|90(?:\.0{1,18})?),(-?(?:1[0-7]|[1-9])?\d(?:\.\d{1,18})?|180(?:\.0{1,18})?)))*$/

Upvotes: 3

Related Questions