'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}");
Solution 1:[1]
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.
Solution 2:[2]
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
Solution 3:[3]
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
Solution 4:[4]
if using .NET why not just use the Regex \d+ and do regex.Matches(..).LastOrDefault();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Ryszard Czech |
Solution 4 | Gabriel |