user10860402
user10860402

Reputation: 1012

Regex that gets the last set of numbers from a string

"abc_d1.txt" should get 0
"abc_d1_2.txt" should get 2
"abc_d1_14.txt" should get 14
"abc_d12_x2_156.txt" should get 156

This is what I've done so far, but I am not getting the right result.

  string y = "tester_yg1.txt";
  string pattern = @"(\d+)(?!.*\d)";
  Regex rg = new Regex(pattern);
  var z = rg.Match(fullFileName).Value;
  Console.WriteLine($"z is {z}");

Upvotes: 4

Views: 445

Answers (4)

Gabriel
Gabriel

Reputation: 635

if using .NET why not just use the Regex \d+ and do regex.Matches(..).LastOrDefault();

Upvotes: 0

Ryszard Czech
Ryszard Czech

Reputation: 18611

Use

(?<![^\W_])\d+(?=\.\w+$)

See proof

Explanation

--------------------------------------------------------------------------------
  (?<!                     look behind to see if there is not:
--------------------------------------------------------------------------------
    [^\W_]                   any character except: non-word
                             characters (all but a-z, A-Z, 0-9, _),
                             '_'
--------------------------------------------------------------------------------
  )                        end of look-behind
--------------------------------------------------------------------------------
  \d+                      digits (0-9) (1 or more times (matching
                           the most amount possible))
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    \.                       '.'
--------------------------------------------------------------------------------
    \w+                      word characters (a-z, A-Z, 0-9, _) (1 or
                             more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    $                        before an optional \n, and the end of
                             the string
--------------------------------------------------------------------------------
  )                        end of look-ahead

Upvotes: 0

The fourth bird
The fourth bird

Reputation: 163207

Another option is to use a single set of positive lookarounds

(?<=_[^\W\d_]\d+_?)\d*(?=\.\w+$)

Explanation

  • (?<= Positive lookbehind, assert what is directly to the left is
    • _[^\W\d_]\d+_? Match _, a word char except digits or _ and 1+ digits followed by an optional _
  • ) Close lookbehind
  • \d* Match 0+ digits (to also get the position when there is no digit)
  • (?= Positive lookahead, assert what is directly to the right is
    • \.\w+$ Match a . and 1+ word characters till the end of string
  • ) Close lookahead

.NET regex demo

enter image description here

Upvotes: 1

Poul Bak
Poul Bak

Reputation: 10929

You can use this regex:

@"(?<=_)\d+(?=\.\w+)|(?<!_\d+)(?=\.\w+)"

Explanation:

(?<=_) look behind for an underscore

\d+ match one or more digits

(?=\.\w+) look ahead for a dot followed by one more word characters (the extension)

| OR

(?<!_\d+) look behind for NOT an underscore followed by one or more digits

(?=\.\w+) look ahead for a dot followed by one more word characters (the extension)

The last part will return an empty match when there's no digit.

Then you will have to convert the empty match to 0 in code.

Update:

To remove the number, you can use this Regex, now call Replace instead:

string pattern1 =  @"_\d+(?=\.\w+)|(?<!_\d+)(?=\.\w+)";
Regex rg1 = new Regex(pattern1);
var z = rg1.Replace(y, "");
string z1  = Path.GetFilename(z);

Now z1 should contain the filename with number and extension removed. When there's no number, it will return the filename without extension.

Upvotes: 0

Related Questions