22

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#

0

5 Answers 5

60

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]]]

Sign up to request clarification or add additional context in comments.

1 Comment

So simple, yet so unknown. @Harry That's the most commonly asked question on Stack Overflow.
7

Do a greedy match up to the last set of [[ and capture..

.*(\[\[.*\]\])\];

See it here.

3 Comments

Looks like it works for Ruby. I'm using c# and I'm using different website to check regex experssions: regexr.com?334dc and it selects the whole string unfortunately
The regex matches the whole string, but the part you're interested in is captured in group #1 (in C# you would use 'Group[1].Value` to extract it). This technique works in every flavor, but .NET also offers a neater option, as my answer explains.
@AlanMoore is correct, generally this is the only way to do it without being able to specify the occurrence (which is language specific). As the question had no reference to C# I could only provide the best language agnostic solution, in future be sure to add all relevant information to the question. +1 for RightToLeft.
5

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();

1 Comment

@user1333853, I added a C# solution
4

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)

Here is the Rubular example

BTW great tool rubular, make me wanna look more into ruby and regular expressions :D

4 Comments

true, thought after ti unescape the ";"
Still over matches and bash isn't required to check as many site exists such rubular.com
nope, this one selects everything startig from the first occurrence on [[
Remove path name from file names: .*\([A-Za-z0-9_$.]+)$
0

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.

Pattern

.*AXDC(?![\s\S]*AXDC).*

Where AXDC is your substring.

Input

this is line 1 with AXDC
this is line 2 with AXDC
this is line 3 with AXDC
this is line 4 with AXDC

Match

this is line 4 with AXDC

Pattern Explanation

  • . 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)

    • \s matches any whitespace character (equivalent to [\r\n\t\f\v ])
    • \S matches any non-whitespace character (equivalent to [^\r\n\t\f\v ])
  • . 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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.