Reputation: 227
I have a string and I need to select the last occurrence of the pattern. The string is:
[[[1302638400000.0, 0], [1302724800000.0, 610.64999999999998], [1302811200000.0, 2266.6500000000001], [1303156800000.0, 4916.9300000000003], [1303329600000.0, 6107.3199999999997], [1303934400000.0, 9114.6700000000001]], [[1302638400000.0, 20000.0], [1302724800000.0, 20000.0], [1302811200000.0, 20000.0], [1303156800000.0, 20000.0], [1303329600000.0, 20000.0], [1303934400000.0, 20000.0]], [[1302638400000.0, 20000.0], [1302724800000.0, 20610.650000000001], [1302811200000.0, 22266.650000000001], [1303156800000.0, 24916.93], [1303329600000.0, 26107.32], [1303934400000.0, 29114.669999999998], [1304452800000.0, 30078.23]], [[1302718580000.0, 0.0], [1302772440000.0, 3.0532500000000073], [1303107093000.0, 11.333250000000007], [1303107102000.0, 21.753250000000008], [1303352295000.0, 24.584650000000003], [1303352311000.0, 26.8766], [1303815010000.0, 30.536599999999996], [1303815028000.0, 27.703349999999993]]];
The pattern that I use is:
\s\[\[(.*?)\]\]
Which unfortunately selects only 1st occurrence. The highlighted text is the desired result. It doesn't matter how many square brackets at the end, just need the last array set.
UPDATE: If it can help you, then the coding is in c#
Upvotes: 22
Views: 29431
Reputation: 311
If you're looking to find the last instance/occurrence of a specific substring within a list of lines, where all lines in the list already contain the substring, you can use the following pattern.
.*AXDC(?![\s\S]*AXDC).*
Where AXDC is your substring.
this is line 1 with AXDC
this is line 2 with AXDC
this is line 3 with AXDC
this is line 4 with AXDC
this is line 4 with AXDC
. matches any character (except for line terminators)
* matches the previous token between zero and unlimited times, as many times as possible, giving back as needed (greedy)
AXDC matches the characters AXDC literally (case sensitive)
Negative Lookahead (?![\s\S]*AXDC)
. matches any character (except for line terminators)
* matches the previous token between zero and unlimited times, as many times as possible, giving back as needed (greedy)
Any online regex matcher tool can be used to get a better explanation for the above pattern. regex101
Upvotes: 0
Reputation: 2530
Try adding the $ to your pattern like this \s\[\[(.*?)\]\]\]\;$
and let me know if it works.
Currently I don't have bash under hand so I cannot check but it should do the trick.
Edit : Right version \S+\s?+(?!((.*\[\[)))
which translates into :
\S : all alfanumeric
\s? : all 1 space occurences
?! : not
.* : everything
\[\[ : until the last pattern of [[ (excluded)
BTW great tool rubular, make me wanna look more into ruby and regular expressions :D
Upvotes: 4
Reputation: 93056
There should be a global flag or a method that returns all matches in your language. Use this and take the last match.
In C# Matches()
returns a MatchCollection
containing all found matches. So you can do for example this:
string source = "[[[1302638400000.0, 0], [1302724800000.0, 610.64999999999998], [1302811200000.0, 2266.6500000000001], [1303156800000.0, 4916.9300000000003], [1303329600000.0, 6107.3199999999997], [1303934400000.0, 9114.6700000000001]], [[1302638400000.0, 20000.0], [1302724800000.0, 20000.0], [1302811200000.0, 20000.0], [1303156800000.0, 20000.0], [1303329600000.0, 20000.0], [1303934400000.0, 20000.0]], [[1302638400000.0, 20000.0], [1302724800000.0, 20610.650000000001], [1302811200000.0, 22266.650000000001], [1303156800000.0, 24916.93], [1303329600000.0, 26107.32], [1303934400000.0, 29114.669999999998], [1304452800000.0, 30078.23]], [[1302718580000.0, 0.0], [1302772440000.0, 3.0532500000000073], [1303107093000.0, 11.333250000000007], [1303107102000.0, 21.753250000000008], [1303352295000.0, 24.584650000000003], [1303352311000.0, 26.8766], [1303815010000.0, 30.536599999999996], [1303815028000.0, 27.703349999999993]]];";
Regex r = new Regex(@"\s\[\[(.*?)\]\]");
MatchCollection result = r.Matches(source);
if (result.Count > 0) {
Console.WriteLine(result[result.Count - 1]);
} else {
Console.WriteLine("No match found!");
}
Console.ReadLine();
Upvotes: 5
Reputation: 75272
Use the RightToLeft
option:
Regex.Match(s, @"\[\[(.*?)\]\]", RegexOptions.RightToLeft)
This option is exclusive to the .NET regex flavor, and does exactly what you asked for: searches from the end of the input instead of the beginning. Of particular note, the non-greedy ?
modifier works just as you expect; if you leave it off you'll get the whole input, but with it you get:
[[1302718580000.0, 0.0], [1302772440000.0, 3.0532500000000073], [1303107093000.0, 11.333250000000007], [1303107102000.0, 21.753250000000008], [1303352295000.0, 24.584650000000003], [1303352311000.0, 26.8766], [1303815010000.0, 30.536599999999996], [1303815028000.0, 27.703349999999993]]]
Upvotes: 60
Reputation: 85883
Do a greedy match up to the last set of [[
and capture..
.*(\[\[.*\]\])\];
See it here.
Upvotes: 7