in reply to Re^3: String expansion script
in thread String expansion script
O.k., here's how I would do it. The following sub is stand-alone. I've changed the spec slightly: lists within curlies are comma-separated rather than colon separated. That seems a bit more natural to me.Indeed just at the same time as the infamous bug popped out, by pure coincidence I had a "real world case" in which it would have been desirable to have list expansion along with range expansion. More precisely, why using two different delimiters where one would suffice? I will use commas to separate items and colons to specify ranges and the former will have precedency over the latter. I think that the following code is self_explanatory:
Example:#!/usr/bin/perl -ln use strict; use warnings; sub expand; sub doit; print for expand $_; sub expand { doit split /\[(.*?)\]/, shift, -1; } sub doit { return @_ if @_ == 1; my ($pre,$pat,$post)=splice @_, 0, 3; map { doit $pre . $_ . $post, @_ } map { /(\w+):(\w+)/ ? $1..$2 : $_ } split /,/, $pat; } __END__
Now you may wonder why I still leave in expand() whereas it's not really needed anymore. Well, this was originally meant as a quick hack, not tremendously concerned with efficiency, for example. But it is somewhat less and less so. So I though: well we can improve it allowing for quoting of "special charachters" here, for example withecho pre_[aa,01:03,bb]_[x,y]_post | ./xstr.pl pre_aa_x_post pre_aa_y_post pre_01_x_post pre_01_y_post pre_02_x_post pre_02_y_post pre_03_x_post pre_03_y_post pre_bb_x_post pre_bb_y_post
instead of the above, and similarly for the regexen specifying for commas and colons. Of course all this would require additional works if we want (as is reasonable) to remove the quoting charachter from output and we (also quite as consistently and reasonably) want to allow one to put literal backslashes there by quoting them the same way (i.e. '\\').sub expand { doit split / (?<!\\)\[ (.*?) (?<!\\)\]/x, shift, -1; }
Once we have done all this, I thought, as a side effect we can have nested patterns, at which point expand() would become handy once again. On a second thought, however, which occurred something like a nanosecond later, i realized that we can't, not so naively at least for this would require to match balanced text.
Now, if we had at our disposal Perl6's rules we could still use a split() statement like the above (modulo any syntactical change). Talking Perl5, I think it should be possible to do it anyway, possibly using some (still marked as) experimental regex feature. Or else we could resort to Text::Balanced in which case I would probably write a separate split()ty sub for clarity, but we would loose the IMHO aesthetically appealing immediateness of the
construct.sub expand { doit split /<SOME_REGEX>/, shift, -1; }
I must say that I am puzzled by the possibility of doing all this with no external module, and I think have devised a relatively simple way to do it, albeit not in one swept but with the aid of some pre and post transformations, which could be sensible after all, since we've never been tremendously concerned about efficiency in the first place, but I will save this for another post!
|
|---|