On Jan 17, 2016, at 11:07 AM, Tom Browder <tom.brow...@gmail.com> wrote:

> I'm trying to write all new Perl code in Perl 6.  One thing I need is
> the equivalent of the Perl 5 qr// and, following Perl 6 docs, I've
> come to use something like this (I'm trying to ignore certain
> directories):
> 
> # regex of dirs to ignore
> my regex dirs {
> \/home\/user\/\.cpan |
> \/home\/tbrowde\/\.emacs
> }
> 
> for "dirlist.txt".IO.lines -> $line {
> # ignore certain dirs
> if $line ~~ m{<dirs>} {
>    next;
> }
> }
> 
> My question: Is there a way to have Perl 6 do the required escaping
> for the regex programmatically, i.e., turn this:
> 
> my $str = '/home/usr/.cpan';
> 
> into this:
> 
> my regex dirs {
> \/home\/usr\/\.cpan
> }
> 
> automatically?

I think that your regex needs anchors to do what you want; 
your current regex will also exclude `/home/user/.cpanabcedfg`, for example.

This is how I do it in Perl 5 (when using regexes instead of a hash):
my $dirs = join '|', map { quotemeta } qw(
   /home/user/.cpan
   /home/tbrowde/.emacs
);
my $dirs_re = qr/^(?:$dirs)$/;

So, `quotemeta` is what you are looking for.
Except that https://design.perl6.org/S29.html#Obsolete_Functions says:
   quotemeta
       Because regex escaping metacharacters can easily be solved by quotes 
       ("Simplified lexical parsing of patterns" in S05), 
       and variables are not automatically interpolated 
       ("Variable (non-)interpolation" in S05), 
       quotemeta is no longer needed.
   http://design.perl6.org/S05.html#Simplified_lexical_parsing_of_patterns
   http://design.perl6.org/S05.html#Variable_%28non-%29interpolation
Summary of `Variable_%28non-%29interpolation`:
In Perl 5, /$var/ deposits the contents of `$var` into the regex,
just like of you had typed them in the source code.
In Perl 6, /$var/ runs quotemeta on the contents of `$var`.
If you want the Perl 5 behavior, then you write it as /<$var>/.
Also, if you embed an array in a regex, it automatically treats it as `|` 
alternatives.
So cool!

# Plain text, *not* regex!
my @dirs_to_skip = <
   /home/user/.cpan
   /home/tbrowde/.emacs
> ;
...
   next if $line ~~ / ^ @dirs_to_skip $ /;

Or, precompiled:
my @dirs_to_skip = <
   /home/user/.cpan
   /home/tbrowde/.emacs
> ;
my $dir_re = / ^ @dirs_to_skip $ /;
...
   next if $line ~~ $dir_re;

If you know that your exclusion list is always literal, 
you can leave the regex engine out of the process, 
and just do a hash lookup
(which is even easier in Perl 6 with `set`, which sets the values all to 
`True`):
my %dirs_to_skip = set <
   /home/user/.cpan
   /home/tbrowde/.emacs
> ;
...
   next if %dirs_to_skip{$line};

-- 
Hope this helps,
Bruce Gray (Util of PerlMonks)

Reply via email to