简体   繁体   中英

What RegEx string will find the last (rightmost) group of digits in a string?

Looking for a regex string that will let me find the rightmost (if any) group of digits embedded in a string. We only care about contiguous digits. We don't care about sign, commas, decimals, etc. Those, if found should simply be treated as non-digits just like a letter.

This is for replacement/incrementing purposes so we also need to grab everything before and after the detected number so we can reconstruct the string after incrementing the value so we need a tokenized regex.

Here's examples of what we are looking for:

  • "abc123def456ghi" should identify the'456'
  • "abc123def456ghi789jkl" should identify the'789'
  • "abc123def" should identify the'123'
  • "123ghi" should identify the'123'
  • "abc123,456ghi" should identify the'456'
  • "abc-654def" should identify the'654'
  • "abcdef" shouldn't return any match

As an example of what we want, it would be something like starting with the name 'Item 4-1a', extracting out the '1' with everything before being the prefix and everything after being the suffix. Then using that, we can generate the values 'Item 4-2a', 'Item 4-3a' and 'Item 4-4a' in a code loop.

Now If I were looking for the first set, this would be easy. I'd just find the first contiguous block of 0 or more non-digits for the prefix, then the block of 1 or more contiguous digits for the number, then everything else to the end would be the suffix.

The issue I'm having is how to define the prefix as including all (if any) numbers except the last set. Everything I try for the prefix keeps swallowing that last set, even when I've tried anchoring it to the end by basically reversing the above.

How about:

^(.*?)(\d+)(\D*)$

then increment the second group and concat all 3.

Explanation:

^         : Begining of string
  (       : start of 1st capture group
    .*?   : any number of any char not greedy
  )       : end group
  (       : start of 2nd capture group
    \d+   : one or more digits
  )       : end group
  (       : start of 3rd capture group
    \D*   : any number of non digit char
  )       : end group
$         : end of string

The first capture group will match all characters until the first digit of last group of digits before the end of the string.

or if you can use named group

^(?<prefix>.*?)(?<number>\d+)(?<suffix>\D*)$

Try next regex:

(\d+)(?!.*\d)

Explanation:

(\d+)           # One or more digits.
(?!.*\d)        # (zero-width) Negative look-ahead: Don't find any characters followed with a digit.

EDIT (OFFTOPIC of the question): : This answer is incorrect but this question has already been answered in other posts so to avoid delete this one I will use this same regex other way, for example in Perl could be used like this to get same result as in C# (increment last digit):

s/(\d+)(?!.*\d)/$1 + 1/e;

您也可以尝试更简单的版本:

(\d+)[^\d]*$

This should do it:

Regex regexObj = new Regex(@"
    # Grab last set of digits, prefix and suffix.
    ^               # Anchor to start of string.
    (.*)            # $1: Stuff before last set of digits.
    (?<!\d)         # Anchor start of last set of digits.
    (\d+)           # $2: Last set of one or more digits.
    (\D*)           # $3: Zero or more trailing non digits.
    $               # Anchor to end of string.
    ", RegexOptions.IgnorePatternWhitespace);

What about not using Regex. Here's code snippet (for console)

string[] myStringArray = new string[] { "abc123def456ghi", "abc123def456ghi789jkl", "abc123def", "123ghi", "abcdef","abc-654def" };

        char[] numberSet = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
        char[] filterSet = new char[] {'a','b','c','d','e','f','g','h','i','j','k','l','m',
                                        'n','o','p','q','r','s','t','u','v','w','x','y','z','-'};
        foreach (string myString in myStringArray)
        {
            Console.WriteLine("your string - {0}",myString);
            int index1 = myString.LastIndexOfAny(numberSet);
            if (index1 == -1)
            Console.WriteLine("no number");
            else
            {
               string mySubString = myString.Substring(0,index1 + 1);
               string prefix = myString.Substring(index1 + 1);
               Console.WriteLine("prefix - {0}", prefix);
               int index2 = mySubString.LastIndexOfAny(filterSet);
               string suffix = myString.Substring(0, index2 + 1);
               Console.WriteLine("suffix - {0}",suffix);
               mySubString = mySubString.Substring(index2 + 1);
               Console.WriteLine("number - {0}",mySubString);
               Console.WriteLine("_________________");
            }
        }
        Console.Read();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM