Subject: | Add globstar functionality |
The bash shell has the ability to consider consecutive asterisks as a wild card that will accept slashes. This is turned on by setting the globstar shell variable.
The attached patches enhance Text::Glob to add this functionality. I have assumed '$globstar' as the name of the global variable that controls this, but the actual name of the variable is unimportant to me. The default is false, under the principal of least surprise.
Subject: | Text-Glob-t.patch |
--- t/Text-Glob.old 2011-02-22 10:08:30.000000000 -0500
+++ t/Text-Glob.t 2013-10-17 18:43:33.000000000 -0400
@@ -1,8 +1,9 @@
#!perl -w
use strict;
-use Test::More tests => 44;
+use Test::More tests => 48;
-BEGIN { use_ok('Text::Glob', qw( glob_to_regex match_glob ) ) }
+BEGIN { use_ok('Text::Glob',
+ qw( glob_to_regex glob_to_regex_string match_glob ) ) }
my $regex = glob_to_regex( 'foo' );
is( ref $regex, 'Regexp', "glob_to_regex hands back a regex" );
@@ -30,6 +31,17 @@
ok( !match_glob( '*.foo', '.file.foo' ), "strict . rule fail" );
ok( match_glob( '.*.foo', '.file.foo' ), "strict . rule match" );
+
+{
+local $Text::Glob::globstar = 1;
+is( glob_to_regex_string( 'fu*bar' ), '(?=[^\.])fu[^/]*bar',
+ 'globstar convert *' );
+ok( !match_glob( 'fu*bar', 'fu/bar' ), 'globstar fail' );
+is( glob_to_regex_string( 'fu**bar' ), '(?=[^\.])fu.*bar',
+ 'globstar convert **' );
+ok( match_glob( 'fu**bar', 'fu/bar' ), 'globstar match' );
+}
+
{
local $Text::Glob::strict_leading_dot;
ok( match_glob( '*.foo', '.file.foo' ), "relaxed . rule" );
Subject: | Text-Glob.patch |
--- lib/Text/Glob.old 2011-02-22 10:08:30.000000000 -0500
+++ lib/Text/Glob.pm 2013-10-17 18:55:48.000000000 -0400
@@ -2,11 +2,12 @@
use strict;
use Exporter;
use vars qw/$VERSION @ISA @EXPORT_OK
- $strict_leading_dot $strict_wildcard_slash/;
+ $strict_leading_dot $strict_wildcard_slash $globstar/;
$VERSION = '0.09';
@ISA = 'Exporter';
@EXPORT_OK = qw( glob_to_regex glob_to_regex_string match_glob );
+$globstar = 0;
$strict_leading_dot = 1;
$strict_wildcard_slash = 1;
@@ -24,7 +25,8 @@
my ($regex, $in_curlies, $escaping);
local $_;
my $first_byte = 1;
- for ($glob =~ m/(.)/gs) {
+ while ($glob =~ m/(.)/gs) {
+ local $_ = $1;
if ($first_byte) {
if ($strict_leading_dot) {
$regex .= '(?=[^\.])' unless $_ eq '.';
@@ -39,8 +41,17 @@
$regex .= "\\$_";
}
elsif ($_ eq '*') {
- $regex .= $escaping ? "\\*" :
- $strict_wildcard_slash ? "[^/]*" : ".*";
+ if ( $escaping ) {
+ $regex .= '\\*';
+ } else {
+ my $more;
+ if ( '*' eq substr $glob, pos $glob, 1 ) {
+ $more = 1;
+ pos $glob += 1;
+ }
+ $regex .= ( $strict_wildcard_slash && ! (
+ $globstar && $more ) ) ? '[^/]*' : '.*';
+ }
}
elsif ($_ eq '?') {
$regex .= $escaping ? "\\?" :
@@ -170,6 +181,10 @@
C<$Text::Glob::strict_wildcard_slash> to a false value with compiling
the regex.
+However, if C<$Text::Glob::globstar> is set to a true value, two
+consecutive asterisks (e.g. C<**.foo>) B<will> match C</>, though one
+asterisk will not.
+
=back
=head1 BUGS