BATsh
view release on metacpan or search on metacpan
lib/BATsh/SH.pm view on Meta::CPAN
# friends). $convert_sub converts one pattern-list alternative (which
# may itself contain nested extglob groups) to a regex fragment.
#
# Returns ($pos_after_close_paren, $regex_fragment), or () when the
# text at $i is not a well-formed extglob group (extglob is then left
# to fall through to its ordinary, literal meaning for that character).
#
# !(list) is approximated as "any run of characters that never forms a
# complete match of one of the alternatives" via a negative lookahead
# repeated per character; this matches the common "exclude these whole
# patterns" usage (e.g. !(*.jpg|*.png)) but, unlike real extglob, is not
# exact when !(...) is combined with more pattern after it in the same
# glob -- documented as a known limitation.
# ----------------------------------------------------------------
sub _extglob_scan {
my ($chars_ref, $i, $convert_sub) = @_;
my @c = @{$chars_ref};
my $n = scalar @c;
return () unless $i+1 < $n && $c[$i+1] eq '(';
my $op = $c[$i];
my $depth = 1;
lib/BATsh/SH.pm view on Meta::CPAN
supported (each alternative is itself recursively brace-expanded).
=head2 Extended Pattern Matching (extglob)
shopt -s extglob # enable; "shopt -u extglob" disables (the default)
shopt extglob # query; "shopt" alone lists all known options
shopt -p extglob # print in "shopt -s/-u extglob" form
case $f in
@(*.tar.gz|*.tgz)) echo archive ;;
!(*.jpg|*.png)) echo not-an-image ;;
esac
echo ${name%%+([0-9])} # strip a trailing run of digits
While C<shopt -s extglob> is active, C<?(list)>, C<*(list)>, C<+(list)>,
C<@(list)>, and C<!(list)> pattern-list operators (C<|>-separated
alternatives, each itself an ordinary glob or a nested extglob group) are
recognised in case patterns and in the C<${VAR%pat}> / C<${VAR%%pat}> /
C<${VAR#pat}> / C<${VAR##pat}> / C<${VAR/pat/rep}> / C<${VAR//pat/rep}>
pattern operand. C<extglob> is off by default, matching bash, and is
lib/BATsh/SH.pm view on Meta::CPAN
C<set -e> / C<-u> / C<-x>.
=head3 Extended Pattern Matching Limitations
=over 4
=item *
Extglob operators are recognised in case patterns and in the
C<${VAR#pat}>-family parameter-expansion patterns only. Pathname
(filename) globbing (C<echo *.@(jpg|png)>) does not expand them: an
unquoted C<(> C<)> is read by the line parser as a subshell command
group long before the word reaches the pathname matcher.
=item *
C<!(list)> is approximated with a repeated negative-lookahead regex
fragment ("any run of characters that never forms a complete match of
one of the alternatives"). This matches the common "exclude these whole
patterns" usage exactly, but is not a byte-for-byte reimplementation of
bash's extglob matcher when C<!(...)> is combined with further pattern
t/0021-sh-extended-features.t view on Meta::CPAN
# EF08: shopt -s extglob enables @(...) alternation in case patterns
sub {
my (undef, $out) = _run_capture(
"shopt -s extglob\ncase abc in\n\@(abc|def)) echo yes ;;\n*) echo no ;;\nesac\n");
ok_is($out, "yes\n", 'EF08 shopt -s extglob: @(a|b) alternation matches');
},
# EF09: extglob !(...) exclusion in case patterns
sub {
my (undef, $out) = _run_capture(
"shopt -s extglob\ncase foo.txt in\n!(*.jpg|*.png)) echo keep ;;\n*) echo skip ;;\nesac\n");
ok_is($out, "keep\n", 'EF09 extglob !(list) exclusion matches');
},
# EF10: here-string feeds a builtin's stdin
sub {
my (undef, $out) = _run_capture("read LINE <<< hello\necho \$LINE\n");
ok_is($out, "hello\n", 'EF10 here-string <<< feeds read');
},
# EF11: here-string content is variable-expanded
t/lib/INA_CPAN_Check.pm view on Meta::CPAN
for my $p (@fb) {
$p =~ s{^\Q$root\E/}{};
}
return @fb;
}
# MANIFEST entries that are text and therefore subject to the encoding
# checks. Anything with a known binary extension is excluded.
sub _text_files {
my ($root) = @_;
return grep { !/\.(?:gz|tgz|zip|tar|bz2|png|jpe?g|gif|ico|pdf)$/i }
_manifest_files($root);
}
# Find $pattern in $path, ignoring POD, __END__, comments, string literals
# and regex literals, so that a match is real code and not prose or data.
# Returns a list of { line => N, text => "..." }.
sub _scan_code {
my ($path, $pattern) = @_;
my $text = _slurp($path);
return () unless $text ne '';
( run in 1.909 second using v1.01-cache-2.11-cpan-788537b7465 )