in reply to How to replace greedy alternation?

It can be done with one regexp.
/^(?=.*a)(?=.*b)(?=.*c).*d/ or die;

If you want to know the order in which they came,

my %order; @order{qw( a b c d )} = map length, /^(?=(.*?)a)(?=(.*?)b)(?=(.*?)c)(.*?)d/ or die; my @ordered = sort { $order{$a} <=> $order{$b} } keys %order;

This is probably slow for long strings.

Update: Actually, no need for a hash.

my @order = map length, /^(?=(.*?)a)(?=(.*?)b)(?=(.*?)c)(.*?)d/ or die; my @ordered = ( qw( a b c d ) )[ sort { $order[$a] <=> $order[$b] } 0..$#order ];

Update: Back to the practical, using multiple regexp and saving @- should be much faster. Especially if scanning for constants.

my @unordered = qw( a b c d ); my @order; for my $s (@unordered) { push @order, /\Q$s/ ? $-[0] : die; } my @ordered = @unordered[ sort { $order[$a] <=> $order[$b] } 0..$#order ];

Replies are listed 'Best First'.
Re^2: How to replace greedy alternation?
by jwkrahn (Abbot) on Jan 28, 2009 at 06:52 UTC

    Another way to do it:

    my %order; /(?=.*(a))(?=.*(b))(?=.*(c))/ and @order{ qw/a b c/ } = @-[ 1 .. $#- ] +;
Re^2: How to replace greedy alternation?
by Anonymous Monk on Jan 28, 2009 at 07:17 UTC
    This code does not work:
    /^(?=.*a)(?=.*b)(?=.*c).*d/
    For example, when used in the code below nothing s returned.
    echo bacd| perl -ne '/^(?=.*a)(?=.*b)(?=.*c).*d/; print "$1 $2 $3\n";'

      That is because there are no capturing parentheses in your regular expression and so $1, $2 and $3 are not affected and thus contain nothing.