Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing a string to a hash

I have a string:

<https://gitlab.me.com/api/v3/projects/all?page=2&per_page=5>;
rel="next",
<https://gitlab.me.com/api/v3/projects/all?page=1&per_page=5>;
rel="first",
<https://gitlab.me.com/api/v3/projects/all?page=8&per_page=5>;
rel="last"

So the format is

(<val>; rel="key")*

And I want to parse that to a hash with the following format:

next => https://gitlab.me.com/api/v3/projects/all?page=2&per_page=5
first => https://gitlab.me.com/api/v3/projects/all?page=1&per_page=5
last => https://gitlab.me.com/api/v3/projects/all?page=8&per_page=5

In Java I would use a regex pattern to extract each key => value pair and put them into a map. The pattern would be something like:

<([^>]++)>;\s*rel="([^"]++)"

Which would give me the key in the second match group and the value in the first. Would the same approach be the best way to achieve this is Perl, or is there something snazzier I could do?

P.S. the reason I'm using Perl rather than Java is that the server doesn't have Java.

like image 510
Boris the Spider Avatar asked Dec 19 '22 14:12

Boris the Spider


1 Answers

My first inclination was to split the string on commas and work with the three substrings, but it is probably better to use a global match ina while loop.

This should do what you want. (Perl is by far the better tool for text processing like this!)

Update I've just realised that your choice of markdown discarded the angle brackets and newlines. Is this more appropriate? I assume it's a multi-line string?

use strict;
use warnings;

my $str = <<'END';
<https://gitlab.me.com/api/v3/projects/all?page=2&per_page=5>;
rel="next",
<https://gitlab.me.com/api/v3/projects/all?page=1&per_page=5>;
rel="first",
<https://gitlab.me.com/api/v3/projects/all?page=8&per_page=5>;
rel="last"
END

my %data;
while ($str =~ / < ([^<>]+) >; \s* rel="([^"]+)" (?:,\s*)? /xg) {
  $data{$2} = $1;
}

use Data::Dump;
dd \%data;

output

{
  first => "https://gitlab.me.com/api/v3/projects/all?page=1&per_page=5",
  last  => "https://gitlab.me.com/api/v3/projects/all?page=8&per_page=5",
  next  => "https://gitlab.me.com/api/v3/projects/all?page=2&per_page=5",
}
like image 114
Borodin Avatar answered Jan 06 '23 03:01

Borodin