Reputation: 3536
I am trying to match the first instance of the value of Timestamp in one expression and the last instance of the value of Timestamp in another expression:
{'Latitude': 50.00001,'Longitude': 2.00002,'Timestamp': '00:10:00'},{'Latitude': 50.0,'Longitude': 2.0,'Timestamp': '00:20:00'},{'Latitude': 50.0,'Longitude': 2.0,'Timestamp': '00:25:00'},{'Latitude': 50.0,'Longitude': 2.0,'Timestamp': '00:37:00'}
Anyone know how to do that.
Upvotes: 0
Views: 47
Reputation: 4657
Take advantage of regexp's greediness: the *
operator will take as many matches as it can find. So the approach here is to match the explicit pattern at the beginning and end of the regexp with a .*
in the middle. The .*
will slurp up as many characters as it can subject to the rest of the regexp also matching.
/(${pattern}).*(${pattern})/
Where here, ${} represents extrapolation. This will vary on your language. In Ruby it would be #{}. I have chosen to capture the entire pattern; you can instead put the () capture around the timestamp value but I find this easier to read and maintain. This regexp will match two instances of $pattern with as much stuff in between as it can fit, thus guaranteeing that you have the first and last.
If you want to be more strict, you could enforce the pattern in the middle as well, *
'ing the full pattern rather than just .
:
/${pattern},\s*(?:${pattern},\s*)*${pattern}/
Ask in the comments if you don't understand any piece of this regexp.
One pattern we can use is /\{[^}]+\'Timestamp\'[^}]+\}/
.Note that this pattern assumes that Timestamp is the LAST key; if this is not always true you need to add a bit more to this pattern.
So the total pattern for the first example will be:
str =~ /(${pattern}.*(${pattern})/
Or, without extrapolation:
str =~ /({[^}]+'Timestamp'[^}]+}).*({[^}]+'Timestamp'[^}]+})/
Then, $1
and $2
are the first and last hashes that match the Timestamp key. Again, this matches the entire pattern rather than only the timestamp value itself, but it should be straightforward from there to extract the actual timestamp value.
For the second, more strict example, and the reason I did not want to capture the timestamp value inside the pattern itself, we have:
str =~ /(${pattern}),\s*(?:${pattern},\s*)*(${pattern})/
Or, without extrapolation:
str =~ /({[^}]+'Timestamp'[^}]+}), *(?:{[^}]+'Timestamp'[^}]+}, *)*({[^}]+'Timestamp'[^}]+})/
We still have the correct results in $1
and $2
because we explicitly chose NOT to put a capturing group inside the pattern.
Upvotes: 2