#1
  1. Born Looser
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2002
    Location
    /root
    Posts
    272
    Rep Power
    173

    Question Conditional regular expression


    Here is the scenario:
    I have an input box.
    It can only accept at the max two comma separated values in the range of 1-63 i.e. 1 and 1,2 is valid input
    If the 2nd value is specified it must be 1 plus the first value, i.e. m,m+1 is valid value.
    My questions is, is it possible to code it thru just one expression?
    Again, following are some valid inputs
    a) m where m can be 1-63
    a) m,m+1 where m can be 1-63 and the value after comma cannot be greater than 63
    Kumar Chetan Sharma
    -----

    _SelfProcclaimedGuru
    Hire a LAMP guy.
    To err is human. To blame your computer for your mistakes is even more human, it is downright natural.
  2. #2
  3. No Profile Picture
    User 165270
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2005
    Posts
    497
    Rep Power
    938
    No, this is not something regex is suitable for. I'm sure there is a regex based solution, but it would be a very terse and complicated beast: regex is not meant for this kind of "numerical matching".
  4. #3
  5. No Profile Picture
    User 165270
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2005
    Posts
    497
    Rep Power
    938
    For my own amusement, I implemented this with regex and came out with the following monstrosity:

    Code:
    ^(?=(?:0,1|1,2|2,3|3,4|4,5|5,6|6,7|7,8|8,9)|(?:9,10|19,20|29,30|39,40|49,50|59,60)|(?:(.)(?:0,\11|1,\12|2,\13|3,\14|4,\15|5,\16|6,\17|7,\18|8,\19|9,\10)))..?,(?:\d|[1-5]\d|6[0-3])$
    Perhaps it can be shortened with some tweaks here and there, but I'm positive that it won't be reduced by much!

    I wrote a little test to see if it really works (which it did):

    Code:
    public class Main {
        
        public static void main(String[] args) throws Exception {
            String[] tests = {
                    "3,4", "45,46", "59,60", "9,10", "19,20",                   // correct
                    "63,64", "98,99", "34,36", "59,61", "3,6", "12,3", "22,33"  // incorrect
            };
            String regex = "^(?=(?:0,1|1,2|2,3|3,4|4,5|5,6|6,7|7,8|8,9)|(?:9,10|19,20|29,30|39,40|49,50|59,60)|(?:(.)(?:0,\\11|1,\\12|2,\\13|3,\\14|4,\\15|5,\\16|6,\\17|7,\\18|8,\\19|9,\\10)))..?,(?:\\d|[1-5]\\d|6[0-3])$";
            for(String t : tests) {
                System.out.printf("Is %5s valid ? %s %s\n", t, t.matches(regex));
            }
        }
    }
    /* Output:
                Is   3,4 valid ? true
                Is 45,46 valid ? true
                Is 59,60 valid ? true
                Is  9,10 valid ? true
                Is 19,20 valid ? true
                Is 63,64 valid ? false
                Is 98,99 valid ? false
                Is 34,36 valid ? false
                Is 59,61 valid ? false
                Is   3,6 valid ? false
                Is  12,3 valid ? false
                Is 22,33 valid ? false
    */
    I guess I made my point that regex is not the right tool for the job. Implementing this with some custom method like his:

    Code:
    public static boolean isValid(String s) {
        if(!s.matches("\\d+,\\d+")) return false;
        String[] tokens = s.split(",");
        int m = Integer.parseInt(tokens[0]);
        int n = Integer.parseInt(tokens[1]);
        if(n > 63) return false;
        return m+1 == n;
    }
    would be much easier to do and even more easier to maintain!

    HTH.


    Edit: the forum software added some white spaces in my regex (as well as in the regex in the Java source) which should be removed. NO idea why the forum acts that way...
    Last edited by prometheuzz; April 1st, 2009 at 03:51 PM.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2004
    Posts
    233
    Rep Power
    76
    Well, it would be awkward to do it with one regex expression. I'm not even sure it's possible. If it is, it would certainly be very inflexible and hard to update/maintain.

    Just wondering if you would be open to doing some If/Then logic, like this:


    air coded ~ VB.NET
    Code:
    Imports System.Text
    
    Public Class Form1
        Private Function DoesItMatch (ByVal pInput As String, ByVal pEvaluator As String) As Boolean
            If RegularExpressions.Regex.IsMatch(pInput, pEvaluator) Then
                Return True
            Else
                Return False
            End If
        End Function
    
        Private Sub MySub()
    
            'Get the string that we want to evaluate
            Dim strInput As String = TextBox1.Text
    
            'Is it one number 1-63?
            Dim boolIsOneNumber As Boolean = DoesItMatch(strInput, "\b[1-63]\b") 'Note: In VB.NET the beginning & end of a string are denoted with a "\b", where in most other RegEx expressions, it is "^" & "$" respectively.
    
            'Is it two numbers 1-63 (separated by a comma)?
            Dim boolIsTwoNumbers As Boolean = DoesItMatch(strInput, "\b[1-63],[1-63]\b")
    
            'If it is two numbers, then check to see if the last number is one higher than the first number
            If boolIsTwoNumbers = True Then
    
                'Split the string into parts (using the comma as a delimiter)
                Dim arrParts() As String = strInput.Split(",")
                If CInt(arrParts(1)) = CInt(arrParts(0)) + 1 Then
                    MessageBox.Show("The second number is one higher than the first number")
                Else
                    MessageBox.Show("The second number is NOT one higher than the first number")
                End If
            End If
        End Sub
    End Class
    Last edited by latrosicarius; April 1st, 2009 at 08:19 PM.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2010
    Posts
    1
    Rep Power
    0

    Just for Fun !


    [CODE]
    echo 3,2 | perl -pi -e 's/(\d+),(\d+)//g;if ($1<$2){ print "T"}else {print "F"};'

    [CODE]

    Comments on this post

    • requinix disagrees : just for fun!
  10. #6
  11. Born Looser
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2002
    Location
    /root
    Posts
    272
    Rep Power
    173

    Not what I was looking for :-)


    Originally Posted by nishnet2002
    [CODE]
    echo 3,2 | perl -pi -e 's/(\d+),(\d+)//g;if ($1<$2){ print "T"}else {print "F"};'

    [CODE]
    I was not looking for what you have given :-)
    Kumar Chetan Sharma
    -----

    _SelfProcclaimedGuru
    Hire a LAMP guy.
    To err is human. To blame your computer for your mistakes is even more human, it is downright natural.
  12. #7
  13. kill 9, $$;
    Devshed Supreme Being (6500+ posts)

    Join Date
    Sep 2001
    Location
    Shanghai, An tSín
    Posts
    6,898
    Rep Power
    3887
    It probably depends on the features of the regexp implementations in whatever language you're using. Perl, for instance, allows code execution within the regexp. That, (although cheating!) makes it easier to do it all-in-one (when was Perl ever the wrong tool for doing everything all at once? )

    For any number:
    Code:
    /^(\d+)(?:,(??{$1+1}))?$/
    A bit more awkward if enforcing 1-63:
    Code:
    /^([1-9]|[1-5]\d|6[0-3])(?:,(??{$1+1}))?$/

IMN logo majestic logo threadwatch logo seochat tools logo