Regular expression to match fractions, not dates

I am trying to find a regular expression that will match part (1/2) but not date (5/5/2005) in a string. Any help at all would be great, all I could find was (\ d +) / (\ d +), which finds matches on both lines. Thank you in advance for your cooperation.

+4
source share
6 answers

Assuming PCRE uses a negative lookahead and lookbehind:

(?<![\/\d])(\d+)\/(\d+)(?![\/\d]) 

The gaze (group (?=) ) Says: "Match this material if it follows this other material." The contents of the viewing window are not matched. We deny it (the group (?!) ) So that it does not match the materials after our fraction - thus, we will not match the group in the future.

In addition to lookahead, lookbehind (a (?<=) Group) does the opposite: it matches materials if it precedes this other material, and just like viewing, we can deny it (group (?<!) ), so that we can match things that don’t follow something.

Together they ensure that our fraction does not have other parts of the fractions before or after it. It does not establish any other arbitrary input requirements. It will correspond to fraction 2/3 in the line "te2/3xt" , unlike most other examples provided.

If your regex flavor uses // to delimit regular expressions, you will have to avoid slash in this or use a different delimiter (Perl m{} would be a good choice here).


Edit: None of these regular expressions seems to work, because the regular expression engine goes back and matches fewer numbers to satisfy the requirements of the regular expression. When I worked on one regular expression for a long time, I sit and decide that maybe one giant regular expression is not the answer, and I am writing a function that uses the regular expression and several other tools for this. You said you were using Ruby. This works for me:

 >> def get_fraction(s) >> if s =~ /(\d+)\/(\d+)(\/\d+)?/ >> if $3 == nil >> return $1, $2 >> end >> end >> return nil >> end => nil >> get_fraction("1/2") => ["1", "2"] >> get_fraction("1/2/3") => nil 

This function returns two parts of the fraction, but returns nil if it is a date (or if there is no fraction). It fails for "1/2/3 and 4/5" , but I don’t know if you want (or need) to get through it. In any case, I recommend in the future, when you ask about stack overflows, "How do I create a regular expression to match this?" you must first step back and see if you can do this using regex and a bit more. Regular expressions are a great tool and can do a lot, but they do not always need to be used alone.


EDIT 2:

I figured out how to solve the problem without resorting to non-regex code, and updated the regex. Now it should work as expected, although I have not tested it. I also went ahead and avoided / , since you still have to do this.

EDIT 3:

I just fixed the j_random_hacker error, indicated in my view and view. I continue to see how much effort is put into this regular expression as proof that a clean regular solution is not necessarily the optimal solution to this problem.

+9
source

Use a negative lookahead and lookbehind .

 /(?<![\/\d])(?:\d+)\/(?:\d+)(?![\/\d])/ 

EDIT: I fixed my trap response for the backtracking error identified by @j_random_hacker. As evidence, I suggest the following quick and dirty php script:

 <?php $subject = "The match should include 1/2 but not 12/34/56 but 11/23, now that ok."; $matches = array(); preg_match_all('/(?<![\/\d])(?:\d+)\/(?:\d+)(?![\/\d])/', $subject, $matches); var_dump($matches); ?> 

which outputs:

 array(1) { [0]=> array(2) { [0]=> string(3) "1/2" [1]=> string(5) "11/23" } } 
+6
source

Lookahead works great if you use Perl or PCRE, but if they are not available in your regular expression engine, you can use:

 (^|[^/\d])(\d+)/(\d+)($|[^/\d]) 

The second and third captured segments will be the numerator and denominator.

If you use the above in a Perl regular expression, be sure to exit / - or use a different delimiter, for example:

 m!(?:^|[^/])(\d+)/(\d+)(?:$|[^/])! 

In this case, you can use (?:...) to avoid storing uninteresting parts in brackets.

EDIT 12/12/2009 : Chris Lutz noticed a dodgy error caused by the retreat that causes most of these answers - I believe it is now fixed in mine.

+4
source

if its entering a string you can try

 ^(\d+)\/(\d+)$ 

otherwise use it maybe

 ^(\d+)\/(\d+)[^\\]*. 
0
source

this will work: (?<![/]{1})\d+/\d+(?![/]{1})

0
source

Depending on the language you are working with, you may try statements with a negative look or look: perl (?! Pattern) states that / pattern / cannot follow a consistent line.

Or, again, depending on the language and everything you know about the context, a word match may be appropriate (\ b in perl).

0
source

All Articles