1

I'm not too familiar with regular expressions in javascript. I'm writing a validation plugin with jquery. I got all my regular expressions done except these two.

//get number in [] from string
foo='text[number]'
//get two numbers from [] the numbers are separated by -
bar='string[num1-num2]'

the numbers can be floats, the length can be anything and there are no spaces. I know I can get the position of portions of the string and get the values that way but I know there should be a way to get it with regular expressions.

Yamiko
  • 4,605
  • 4
  • 26
  • 48
  • Out of interest, can the numbers be negative? For example, is `string[123--456]` valid? And if that is the case, would `abc[-123]` be considered valid in the first example or invalid in the second? – Jonathon Bolster Oct 12 '11 at 16:19

2 Answers2

2
var myregexp = /\[([\-+]?\b\d*\.?\d+\b)(?:\b-([\-+]?\d*\.?\d+\b))?\]/;
var match = myregexp.exec(subject);
if (match != null) {
    num1= match[1];
    num2 = match[2]; //maybe null if you have single number!
} else {
    num1 = num2 = "";
}

This will match any floating points inside your brackets unless it is specified in a scientific form.

Test :

//get number in [] from string
foo='text[20938423.20938]'
//get two numbers from [] the numbers are separated by -
bar='string[23.20-23]'
//another test
bar='string[23.20-.9873]'

Output :

Group 1 :

20938423.20938
23.20
23.20

Group 2 :

23
.9873
FailedDev
  • 25,171
  • 9
  • 48
  • 70
1

Regex to match a decimal integer or floating point "number":

Crafting an accurate regex to match a "number" is not as simple as it may first appear! (Just ask tchrist who explained it quite thoroughly in his excellent: "What’s a Number?" answer). For the purpose of the answer here, lets assume a "number" is defined as follows:

  • All numbers are decimal and no suffixes are allowed. (No octal, hex or binary numbers.)
  • The integer, fraction and exponent parts consist of a sequence of decimal digits.
  • The integer and exponent parts may be prefixed with an optional plus or minus sign and may have leading zeroes.
  • Either the integer part or the fraction part may be missing, but not both.
  • The exponent part is optional.

Given these requirements, here are examples of valid "number" representations, divided into two types; Type 1: numbers having an integer portion and Type 2: numbers without an integer portion.

Type 1: Required integer part. Optional decimal point with optional fractional digits and optional exponent:

1 +1 -1
1. +1. -1.
1.1 +1.1 -1.1
1E1 1E+1 1E-1
1.E1 1.E+1 1.E-1
1.1E1 1.1E+1 1.1E-1

Type 2: No integer part. Required decimal point and fractional digits. Optional exponent.

.1 +.1 -.1
.1E1 .1E+1 .1E-1

Here is a regex which matches all of the above number representations (written in PHP free-spacing format for readability):

$re_number = '/
    # Match a decimal integer or floating point "number".
    [+\-]?      # Optional leading sign.
    (?:         # Non-capture group for types 1 & 2.
      \b        # Either type 1: Number has integer part.
      [0-9]+    # Required whole integer part.
      (?:       # Optional fractional part.
        \.      # Required decimal point.
        [0-9]*  # Zero or more fractional digits.
      )?        # Fractional part is optional.
    |           # or Type 2: Number has no integer part.
      \B        # Leading "." is NOT on a word boundary.
      \.        # Required decimal point.
      [0-9]+    # Required fractional digits.
    )           # End group of type 1 & 2 alternatives.
    (?:         # Optional exponent.
      [Ee]      # Exponent begins with required literal E
      [+\-]?    # Optional leading sign.
      [0-9]+    # Required exponent number part.
    )?          # End optional exponent.
    /x';

Here is the same regex in Javascript syntax (with all comments removed):

var re_number =
    /[+\-]?(?:\b[0-9]+(?:\.[0-9]*)?|\B\.[0-9]+)(?:[Ee][+\-]?[0-9]+)?/;

Solution to OP question:

The OP wants to match either one or two "numbers" enclosed within square brackets. If there are two numbers, they are separated by a dash. Given the above defintion of a "number", here is a regex solution which meets these requirements:

$re_1_or_2_numbers_in_brackets = '/
    # Match one or two "numbers" inside square brackets.
    \[            # Literal left opening square bracket.
    [+\-]?        # Optional leading sign.
    (?:           # Non-capture group for types 1 & 2.
      \b          # Either type 1: Number has integer part.
      [0-9]+      # Required whole integer part.
      (?:         # Optional fractional part.
        \.        # Required decimal point.
        [0-9]*    # Zero or more fractional digits.
      )?          # Fractional part is optional.
    |             # or Type 2: Number has no integer part.
      \B          # Leading "." is NOT on a word boundary.
      \.          # Required decimal point.
      [0-9]+      # Required fractional digits.
    )             # End group of type 1 & 2 alternatives.
    (?:           # Optional exponent.
      [Ee]        # Exponent begins with required literal E
      [+\-]?      # Optional leading sign.
      [0-9]+      # Required exponent number part.
    )?            # End optional exponent.
    (?:           # Group for optional second "number".
      -           # Required - separator for second number.
      [+\-]?      # Optional leading sign.
      (?:         # Non-capture group for types 1 & 2.
        \b        # Either type 1: Number has integer part.
        [0-9]+    # Required whole integer part.
        (?:       # Optional fractional part.
          \.      # Required decimal point
          [0-9]*  # Zero or more fractional digits.
        )?        # Fractional part is optional.
      |           # or Type 2: Number has no integer part.
        \B        # Leading "." is NOT on a word boundary.
        \.        # Required decimal point.
        [0-9]+    # Required fractional digits.
      )           # End group of type 1 & 2 alternatives.
      (?:         # Optional exponent.
        [Ee]      # Exponent begins with required literal E
        [+\-]?    # Optional leading sign.
        [0-9]+    # Required exponent number part.
      )?          # End optional exponent.
    )?            # Second number is optional.
    \]            # Literal right closing square bracket.
    /x';

Here is the same regex in Javascript syntax (with all comments removed):

var re_1_or_2_numbers_in_brackets =
    /\[[+\-]?(?:\b[0-9]+(?:\.[0-9]*)?|\B\.[0-9]+)(?:[Ee][+\-]?[0-9]+)?(?:-[+\-]?(?:\b[0-9]+(?:\.[0-9]*)?|\B\.[0-9]+)(?:[Ee][+\-]?[0-9]+)?)?\]/;

This solution correctly matches all of the following variations:

[1-1] [+1-+1] [-1--1]
[1.-1.] [+1.-+1.] [-1.--1.]
[1.1-1.1] [+1.1-+1.1] [-1.1--1.1]
[1E1-1E1] [1E+1-1E+1] [1E-1-1E-1]
[1.E1-1.E1] [1.E+1-1.E+1] [1.E-1-1.E-1]
[1.1E1-1.1E1] [1.1E+1-1.1E+1] [1.1E-1-1.1E-1]
[.1-.1] [+.1-+.1] [-.1--.1]
[.1E1-.1E1] [.1E+1-.1E+1] [.1E-1-.1E-1]

Community
  • 1
  • 1
ridgerunner
  • 30,685
  • 4
  • 51
  • 68
  • thank you. can you please explain \b and \B in more detail. what I have read on it online is vague and I dont quite understand it. a word boundary would be the first or last letter in a string? – Yamiko Oct 12 '11 at 23:38
  • the other detail I don't understand is ?: E.g: /(d).\1/ matches and captures 'dad' in "abcdadef" while /(?:.d){2}/ matches but doesn't capture 'cdad'. from http://www.javascriptkit.com/javatutors/redev2.shtml doesnt seem to be right or am I greatly misunderstanding what they're saying. – Yamiko Oct 12 '11 at 23:45
  • The `\b` is a word boundary assertion which matches a _position_ between a word character and a non-word character. With Javascript a word character (which can be represented with a `\w` or `[A-Za-z0-9_]` ), is a character that is a digit or a letter or an underscore. The `\B` is an assertion of a position that is NOT on a word boundary. As you have already surmised, `(...)` is a capturing parentheses and `(?:...)` is a non-capturing parentheses. Check out [regular-expressions.info](http://www.regular-expressions.info/) for more regex fun! – ridgerunner Oct 13 '11 at 00:45