Zaibes
Zaibes

Reputation: 37

Regexp match until

I have the following string:

{"name":"db-mysql","authenticate":false,"remove":false,"skip":false,"options":{"create":{"Image":"mysql:5.6/image-name:0.3.44","Env":{"MYSQL_ROOT_PASSWORD":"dummy_pass","MYSQL_DATABASE":"dev_db"}}}}

I need to get the version: 0.3.44

The pattern will always be "Image":"XXX:YYY/ZZZ:VVV"

Any help would be greatly appreciated

Rubular link

Upvotes: 1

Views: 64

Answers (2)

John Bollinger
John Bollinger

Reputation: 180201

This regular expression will reliably match the given "pattern" in any string and capture the group designated VVV:

/"Image":"[^:"]+:[^"\/]+\/[^":]+:([^"]+)"/

where the pattern is understood to express the following characteristics of the input to be matched:

  • there is no whitespace around the colon between "Image" and the following " (though that could be matched with a small tweak);
  • the XXX and ZZZ substrings do contain any colons;
  • the YYY substring does not contain a forward slash (/); and
  • none of the substrings XXX, YYY, ZZZ, or VVV contains a literal double-quote ("), whether or not escaped.

Inasmuch as those constraints are stronger than JSON or YAML requires to express the given data, you'd probably be better off using using a bona fide JSON / YAML parser. A real parser will cope with semantically equivalent inputs that do not satisfy the constraints, and it will recognize invalid (in the JSON or YAML sense) inputs that contain the pattern. If none of that is a concern to you, however, then the regex will do the job.

Upvotes: 2

ikegami
ikegami

Reputation: 385809

This is extremely hard to do correctly using just a regular expression, and it would require an regex engine capable of recursion. Rather than writing a 50 line regexp, I'd simply use an existing JSON parser.

$ perl -MJSON::PP -E'
   use open ":std", ":encoding(UTF-8)";
   my $json = <>;
   my $data = JSON::PP->new->decode($json);
   my $image = $data->{options}{create}{Image};
   my %versions = map { split(/:/, $_, 2) } split(/\//, $image);
   say $versions{"image-name"};
' my.json
0.3.44

Upvotes: 1

Related Questions