It may look ugly, but
my $quoted = qr/'[^']+'/;  # ' fix Stackoverflow highlighting
my %_extract_wanted_cache;
sub extract_wanted_memo { 
  my($string, $index) = @_;
  $string =~ ($_extract_wanted_cache{$index} ||=
                qr/^(?:.*?$quoted.*?){@{[$index-1]}}($quoted)/)
    ? $1
    : ();
}
benchmarking suggests it might be worthwhile:
sub extract_wanted { 
  my($string, $index) = @_;
  $string =~ /^(?:.*?$quoted.*?){@{[$index-1]}}($quoted)/
    ? $1
    : ();
}
sub extract_wanted_gindex {
  my($string, $index) = @_;
  ($string =~ /$quoted/g)[$index-1];
}
use Benchmark;
timethese -1 => {
  nocache => sub { extract_wanted        $string2, 3 },
  memoize => sub { extract_wanted_memo   $string2, 3 },
  index   => sub { extract_wanted_gindex $string2, 3 },
  nocache_fail => sub { extract_wanted        $string2, 100 },
  memoize_fail => sub { extract_wanted_memo   $string2, 100 },
  index_fail   => sub { extract_wanted_gindex $string2, 100 },
}
Results:
Benchmark: 
running
 index, index_fail, memoize, memoize_fail, nocache, nocache_fail
 for at least 1 CPU seconds
...
     index:   1 w/c secs (1.04 usr + 0.00 sys = 1.04 CPU) @183794.23/s (n=191146)
index_fail:   1 w/c secs (1.03 usr + 0.00 sys = 1.03 CPU) @185578.64/s (n=191146)
   memoize:   1 w/c secs (1.00 usr + 0.00 sys = 1.00 CPU) @264664.00/s (n=264664)
memoize_fail: 0 w/c secs (1.03 usr + 0.00 sys = 1.03 CPU) @835106.80/s (n=860160)
   nocache:   0 w/c secs (1.03 usr + 0.00 sys = 1.03 CPU) @196495.15/s (n=202390)
nocache_fail: 2 w/c secs (1.03 usr + 0.00 sys = 1.03 CPU) @445390.29/s (n=458752)