Почему это регулярное выражение не удаляет последние пробелы из текста Pod :: Usage? - PullRequest
1 голос
/ 10 июня 2011

Я работаю над модулем, который опирается на Pod :: Usage , чтобы проанализировать POD вызывающего скрипта и затем отправить текст использования, справки и man в скалярную переменную.Мне нужно было удалить последние пробелы из этого текста, поэтому я использовал простое регулярное выражение, которое, как я думал, сработало.И это произошло ... но с перерывами.

Вот демонстрация проблемы.Мы будем благодарны за любые идеи.

Неожиданное поведение (т. Е. Невозможность регулярного выражения удалить последние переводы строк) происходит последовательно на моей машине Solaris с Perl 5.10.1.В Windows с Perl 5.12.1 поведение нестабильно (выходные данные приведены ниже).

use strict;
use warnings;

use Pod::Usage qw(pod2usage);
use Test::More;

# Baseline test to show that the regex works.
my $exp                      = "foo\nbar\n...";
my $with_trailing_whitespace = $exp . "   \n\n";
$with_trailing_whitespace    =~ s!\s+\Z!!;
my $ords = get_ords_of_final_chars($with_trailing_whitespace);
is_deeply $ords, [46, 46, 46]; # String ends with 3 periods (not whitespace).

# Run a similar test, using text from Pod::Usage.
for (1 .. 2){
    my $pod = get_pod_text();
    $ords = get_ords_of_final_chars($pod);
    is_deeply $ords, [46, 46, 46];
}

done_testing();

sub get_ords_of_final_chars {
    # Takes a string. Return array ref of the ord() of last 3 characters.
    my $s = shift;
    return [ map ord(substr $s, - $_, 1), 1 .. 3 ];
}

sub get_pod_text {
    # Call pod2usage(), sending output to a scalar.
    open(my $fh, '>', \my $txt) or die $!;
    pod2usage(-verbose => 2, -exitval => 'NOEXIT', -output  => $fh);
    close $fh;   # This doesn't help.

    # Here's the same regex as above.
    # 
    # If I use chomp(), the newlines are consistently removed:
    #     1 while chomp($txt);
    $txt =~ s!\s+\Z!!;
    return $txt; 
}

__END__

=head1 NAME

sample - Some script...

=head1 SYNOPSIS

foo.pl ARGS...

=head1 DESCRIPTION

This program will read the given input file(s) and do something
useful with the contents thereof...

=cut

Вывод в моем окне Windows:

$ perl  demo.pl
ok 1
not ok 2
#   Failed test at demo.pl line 18.
#     Structures begin differing at:
#          $got->[0] = '10'
#     $expected->[0] = '46'
not ok 3
#   Failed test at demo.pl line 18.
#     Structures begin differing at:
#          $got->[0] = '10'
#     $expected->[0] = '46'
1..3
# Looks like you failed 2 tests of 3.

$ perl  demo.pl
ok 1
ok 2
ok 3
1..3

Ответы [ 2 ]

4 голосов
/ 10 июня 2011

Ну, чтобы процитировать perlre :

\Z Match only at end of string, or before newline at the end
\z Match only at end of string

Итак, вы должны использовать $txt =~ s!\s+\z!!; (строчные буквы z).\s+ жадный, я бы все равно ожидал, что это сработает.Может быть, это ошибка Perl.

1 голос
/ 13 июня 2011

Хотя другие плакаты верны относительно \ z \ Z $, между прочим, я не получаю никаких сбоев на win32

$ perl -d:Modlist demo.pl
ok 1
ok 2
ok 3
1..3
Carp                   1.17
Config
Encode                 2.43
Encode::Alias          2.14
Encode::Config         2.05
Encode::Encoding       2.05
Exporter             5.64_01
Exporter::Heavy      5.64_01
File::Spec             3.33
File::Spec::Unix       3.33
File::Spec::Win32      3.33
PerlIO                 1.06
PerlIO::scalar         0.08
Pod::Escapes           1.04
Pod::InputObjects      1.31
Pod::Parser            1.37
Pod::Select            1.36
Pod::Simple            3.16
Pod::Simple::BlackBox   3.16
Pod::Simple::LinkSection   3.16
Pod::Text              3.15
Pod::Usage             1.36
Test::Builder          0.98
Test::Builder::Module   0.98
Test::More             0.98
XSLoader               0.15
base                   2.15
bytes                  1.04
integer                1.00
overload               1.10
vars                   1.01
warnings               1.09
warnings::register     1.01
...