Home > Blockchain >  How to export a regex from a module
How to export a regex from a module

Time:11-17

I have a regex which I wish to export from my module, the code is as follows :

package regExport;
use strict;
use warnings;
use Exporter qw(import);
our @EXPORT_OK = qw(re);

my re = /.../; # my regex is here

and its being imported here

use regExport qw(re);
my @li = ("man", "qwrt", "mnbv", "azx", "aeiou");

foreach my $st (@li) {
     $li =~ a/b/; # I wish to test my regex on each of these strings
}

Anyone has any ideas how I would go about doing that. I'm feeling fairly confused on how to go about doing that.

CodePudding user response:

The simplest take, but which is not the best (see below), would be to make a variable with a pattern. Best use qr operator for that, and then can export the variable

package RegExport;

use strict;
use warnings;

use Exporter qw(import);
our @EXPORT_OK = qw($re_pattern);

our $re_pattern = qr/(\w )/i;  # capture a "word" case-insensitive

1;

Note that I've capitalized the package name, per the usual Perl convention of Pascal case. (Then the file name need follow that and be RegExport.pm.)

This is then used as

use warnings;
use strict;
use feature 'say';

use FindBin qw($RealBin);
use lib $RealBin;

use RegExport qw($re_pattern);

my $text = q(Some text with a bunch of words. In sentences.);

while ($text =~ /$re_pattern/g) { 
    say "Word: $1";
}

Here I expect RegExport.pm to be in the same directory as the program. The use of $RealBin is a good way to add to the search path for included libraries a directory relative to where the program itself is (in this case, the program's very directory).

If you really want to go with a variable like this (but read on!) then there is no need to export it from its package, but can use its fully qualified name in the caller

use RegExport;

... $RegExport::re_pattern ...

This is what is sometimes done in libraries for various settings.

However, the documentation has a bit to say about this, in a section What not to export

Do not export variable names.

@EXPORT_OK = qw($svar @avar %hvar); # DON'T!

Exporting variables is not a good idea. They can change under the hood, provoking horrible effects at-a-distance that are too hard to track and to fix. Trust me: they are not worth it.

This good advice is occasionally violated in libraries, to a good effect; an example is $RealBin used above. But if you have no overriding reasons for that then better follow it -- and use a function to return the value

package RegExport;

use strict;
use warnings;

use Exporter qw(import);
our @EXPORT_OK = qw(get_pattern);

sub get_pattern {
    my @specs = @_;  # any input on how to form the pattern

    my $re_pattern = qr{...};

    return $re_pattern;
}

1;

and now you use it as

use RegExport qw(get_pattern);

my $re = get_pattern();   # or pass extra rules for how to form it

and use $re in a regex as a ready pattern.

Now both the users of this code and the future code maintainers are happy.

CodePudding user response:

You were close. There were just a few problems with your code:

  • Variables you want to export to another package (i.e. main) need to be declared as package variables (with our) rather than lexical variables (with my).
  • You're calling the match operator (/ ... /) rather than declaring and creating a regex. You need qr/ ... / instead.
  • Although you loaded Exporter, you also need to make your class a subclass in order to use import().
  • Your package needs to return a true value at the end.

So I have this in the module:

package RegExport;

use strict;
use warnings;

use Exporter;

our @ISA = qw(Exporter);
our @EXPORT = qw($re);

our $re = qr/[aeiou]/; # my regex is here
    
1;

And this in the test program:

use lib '.';
use feature 'say';

use RegExport;

my @li = ("man", "qwrt", "mnbv", "azx", "aeiou");
    
foreach my $st (@li) {
  if ($st =~ /$re/) {
    say "Match: $st";
  } else {
    say "No match: $st";
  }
}

Note that I've changed the name of your package to RegExport. It's a tradition in Perl that standard user-defined modules start with a capital letter.

  • Related