Strange RegExp problem

Discussion in 'Javascript' started by r@ph, Oct 14, 2008.

  1. r@ph

    r@ph Guest

    Hello,

    It seems delimiters can cause trouble sometimes.

    Look at this :

    <script type="text/javascript">
    function isDigit(s) {
    var DECIMAL = '\\.';
    var exp = '/(^[+]?0(' + DECIMAL
    +'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL
    +'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL +'0+$)/';
    return RegExp(exp).test(s);
    };
    document.write(isDigit('123.45') ? '1' : '0');
    document.write(isDigit('123') ? '1' : '0');
    document.write(isDigit('123.00') ? '1' : '0');
    </script>

    With / delimiters, third test fails.
    With | delimiters, it's ok.

    Same behavior with firefox,ie7,safari.

    Can someone explain this ?

    Thanks.
     
    r@ph, Oct 14, 2008
    #1
    1. Advertising

  2. r@ph wrote:

    > var exp = '/(^[+]?0(' + DECIMAL
    > +'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL
    > +'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL +'0+$)/';
    > return RegExp(exp).test(s);


    // serve as delimiters for regular expression literals. You don't use
    them in strings passed to the RegExp constructor, unless you really want
    to match a slash.

    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Oct 14, 2008
    #2
    1. Advertising

  3. r@ph

    r@ph Guest

    >> var exp = '/(^[+]?0(' + DECIMAL
    >> +'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL
    >> +'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL +'0+$)/';
    >> return RegExp(exp).test(s);


    > // serve as delimiters for regular expression literals. You don't use them
    > in strings passed to the RegExp constructor, unless you really want to
    > match a slash.



    Hi Martin,
    Can you explain this a little more please ?
    In my sample, why only the 3rd case fails ?
    Thanks a lot.
     
    r@ph, Oct 14, 2008
    #3
  4. "r@ph" <> writes:

    > It seems delimiters can cause trouble sometimes.


    No doubt. Most things can :)

    > Look at this :
    >
    > <script type="text/javascript">
    > function isDigit(s) {
    > var DECIMAL = '\\.';
    > var exp = '/(^[+]?0(' + DECIMAL
    > +'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL
    > +'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL +'0+$)/';


    ICK. Now I have looked. I need to go wash my eyes. With soap.

    Ahem, anyway ...
    The "/" at the start and end of "exp" is pretty certainly wrong.

    A javascript regexp *literal* is delimited by slashes, e.g.,
    /foo|bar/. The corresponding constructor call would be RegExp("foo|bar"),
    where the regexp is in a string literal, delimited by the string quotes,
    and therefore doesn't need any other delimination ... deliminion ...
    something.

    The "/"'s above merely cause the first and last alternative of the
    regexp to fail because they expect a slash before the start of the
    string, or after the end.

    > return RegExp(exp).test(s);
    > };
    > document.write(isDigit('123.45') ? '1' : '0');
    > document.write(isDigit('123') ? '1' : '0');
    > document.write(isDigit('123.00') ? '1' : '0');
    > </script>
    >
    > With / delimiters, third test fails.
    > With | delimiters, it's ok.


    Where did you put the '|' "delimiters"? In the same palce as the '/'?
    Then the first and last alternative would start to work, and you would
    also have added two ways of matching the empty substring, meaning that
    *all* strings would match. Try isDigit("Arglebargle").

    > Same behavior with firefox,ie7,safari.


    Then it's probably intended behavior.

    > Can someone explain this ?


    Yep, it's what you asked for :)

    Stick to regexp literals if possible, they are easier to read,, and
    you don't have to escape your backslashes.

    > var exp = '/(^[+]?0(' + DECIMAL
    > +'0+)?$)|(^([-+]?[1-9][0-9]*)$)|(^([-+]?((0?|[1-9][0-9]*)' + DECIMAL
    > +'(0*[1-9][0-9]*)))$)|(^[-+]?[1-9]+[0-9]*' + DECIMAL +'0+$)/';


    If I read the regexp correctly, it should match any of:
    - An optional plus and a single zero, optionally followed by a decimal
    point and one or more zeros.
    - An optional sign and a non-zero digit followed by any number of digits.
    - An optional sign and either zero or (a non-zero digit followed by any
    number of digits), followed by a decimal point and a sequence of digits
    containing at least one non-zero digit.
    - An optional sign and a non-zero digit followed by any number of digits,
    followed by a decimal point and a nonzero number of zeros.

    I.e., an optional sign, either a single zero multiple digits not startine
    with a zero, and optionally a decimal point and more than one digit -
    except you don't allow minus zero.

    It might be easier to use two checks:

    /^[-+]?(?:0|[1-9]\d+)(?:\.\d+)?$/
    AND NOT
    /^-0(?:\.0+)$/

    If that's not possible, I think the above can also be made a little
    shorter (and avoid the DECIMAL constant, unless you do it for
    readablilty):
    /^(?:\+?0(?:\.0+)?|[-+]?(?:0\.0*[1-9]\d*|[1-9]\d*(?:\.\d+)?))$/

    Best of luck.
    /L 'likes regexps'
    --
    Lasse Reichstein Holst Nielsen
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Oct 14, 2008
    #4
  5. r@ph

    r@ph Guest

    Hello,

    Thanks for this complete answer.

    > A javascript regexp *literal* is delimited by slashes, e.g.,
    > /foo|bar/. The corresponding constructor call would be RegExp("foo|bar"),
    > where the regexp is in a string literal, delimited by the string quotes,
    > and therefore doesn't need any other delimination ... deliminion ...
    > something.


    Understood.

    > Where did you put the '|' "delimiters"? In the same palce as the '/'?
    > Then the first and last alternative would start to work, and you would
    > also have added two ways of matching the empty substring, meaning that
    > *all* strings would match. Try isDigit("Arglebargle").


    Exact. I'm confused :S


    This code and my problem come from the tablesorter jquery plugin. I warn the
    author now.

    Thanks again.
    Raph
     
    r@ph, Oct 14, 2008
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Greg Hurrell
    Replies:
    4
    Views:
    163
    James Edward Gray II
    Feb 14, 2007
  2. Mikel Lindsaar
    Replies:
    0
    Views:
    488
    Mikel Lindsaar
    Mar 31, 2008
  3. Joao Silva
    Replies:
    16
    Views:
    363
    7stud --
    Aug 21, 2009
  4. Uldis  Bojars
    Replies:
    2
    Views:
    192
    Janwillem Borleffs
    Dec 17, 2006
  5. Matìj Cepl

    new RegExp().test() or just RegExp().test()

    Matìj Cepl, Nov 24, 2009, in forum: Javascript
    Replies:
    3
    Views:
    181
    Matěj Cepl
    Nov 24, 2009
Loading...

Share This Page