I think your last proposition (first unpacking the count, then generating a template using it) is probably your best option, most readable.
You might be able to achieve what you want with something like the code below, but it really lacks clarity when you want to read something longer than a byte:
use Data::Dump qw( pp );
my $str = pack "C (a)*", 4, 'a'..'z';
pp unpack 'C/a @0 CXC/x/a @0 CXCXC/x/x/a', $str;
("abcd", "efgh", "ijkl")
- You already know what C/a does. => the stack is ("abcd") and pos = 5
- @0 goes back to the start. => the stack is ("abcd") and pos = 0
CXC reads the first value, goes back one byte, and reads it again => the current list is ("abcd", 4, 4) and pos = 1
/x removes the last value in the list (4) and uses it as a repeat count for x, which just skips a byte (so /x ignores four bytes) => the list is ("abcd", 4)
and pos = 5
/a removes the last value in the list (4 again), and uses it as a repeat count for a => the list is ("abcd", "efgh") and pos = 9
@0 goes back the start, CXCXC reads the count three times, /x/x uses the count twice to skip bytes, and /a reads the last substring.
This gets harder when you want to skip more than one byte at a time. This can be done with x[V] which means "skip as many bytes as there are in V". But you can't write C/x[V] because the x would have two counts (one explicit, and one from the stack). So you have to write C/(x[V]) where you apply C times the group "skip as many bytes as in V".
However, at least in my version of perl, you can't use:
CXC /(x[a]) /a because skipping a group seems to change the stack and add an element that is used instead of the correct value. It kind of looks like after C/a CXC /(x[a]) the stack is actually ("abcd", 4, ()) instead of ("abcd", 4). That extra element is removed if you add "xX" which skips one byte forward, and skips one byte backward. This doesn't do anything useful, except the next /a does what you want.
This leads to :
pp unpack 'C/a @0 CXC /(x[a]) xX /a @0 CXC /((x[a])2) xX /a', $str;
Once again, your last proposition is probably a better solution.