raku

How should Regexes be passed to MAIN in Raku?


Is there an idiomatic way to pass a Regex from the command line to a Raku program. The following code accomplishes what I'm trying to do but it has a few issues (see below).

#!/bin/raku

use MONKEY-TYPING;
augment class Str {
  method Regex { 
    my $tmp = self.Str;
    return rx/ <$tmp> /;
  }
}

sub MAIN (Regex(Str) $sample) {
  if ( "hello world" ~~ $sample ) {
    say "hello world";
  }
}

Issues

  1. This changes the default Str class which may cause unexpected behavior down the road.
  2. Regexes passed to this work but sometimes act strange. For example:

this works:

$ ./cliRegex.raku '.*'
hello world

this does not work:

$ ./cliRegex.raku .*
Usage:
  ./cliRegex.raku <sample>

Solution

  • The below code checks if a string is a valid regex. It doesn't prevent the code injection mentioned by librasteve. It is simply intended to demonstrate using subset for validating a regex passed to MAIN in a file named cliRegex.raku.

    #! /bin/raku
    
    # returns true if needle is a valid regex
    sub regexIsValid ( Str $needle ) returns Bool {
      try {
        "abcd" ~~ rx/ <$needle> /;
        return True;
      }
      die "Invalid regex: '$needle'\n$!\n\nSee `cliRegex.raku --help` for usage";
    }
    
    subset Validregex of Str where regexIsValid($_);
    
    sub MAIN (
      Validregex $sample #= pass regex to sample to test if it's a regex 
    ) {
      if ( "hello world" ~~ rx/ <$sample> / ) {
        say "hello world";
      }
    }
    

    Examples

    Valid Regex Passed

    $ raku ./cliRegex.raku '.*'
    hello world
    

    Invalid Regex Passed

    $ raku ./cliRegex.raku '*'
    Invalid regex: '*'
    Quantifier quantifies nothing
    
    See `program.raku --help` for usage
      in sub regexIsValid at ./cliRegex.raku line 9
      in block <unit> at ./cliRegex.raku line 12