如何在 Perl 中打印外部命令的过滤输出列表?

How to print filtered output list of an external command in Perl?

我正在学习 Perl。作为练习者,我尝试打印所有已安装的 Mojolicious 模块。我正在使用 Strawberry Perl,但没有安装 grep

我天真的尝试是:

perl -wE "for (sort `cpan -l`) { chomp; say if index($_, 'Mojo') == 0; };"

我发现 cpan -l returns 一个列表。我期待一个字符串,但没关系。我 sort 返回的列表,chomp 每条记录和 say 以 'Mojo'.

开头的记录

它确实有效,但每行打印两次:

Mojolicious::Sessions   undef
Mojolicious::Sessions   undef
Mojolicious::Static     undef
Mojolicious::Static     undef
Mojolicious::Types      undef
Mojolicious::Types      undef
Mojolicious::Validator  undef
Mojolicious::Validator  undef
Mojolicious::Validator::Validation      undef
Mojolicious::Validator::Validation      undef

每条记录打印两次是什么错误?

编辑:

我运行分OS下的代码。看起来它工作正常但安装了两个版本的库。

perl -we 'for (sort `cpan -l`) { chomp; print $_, "\n" if index($_, "JSON") == 0; };'

JSON::PP        4.02
JSON::PP        4.04
JSON::PP::Boolean       4.02
JSON::PP::Boolean       4.04

编辑 2:

根据@zdim 的建议,我检查了已安装模块的文件路径。似乎有双倍安装:

whichpm -a Mojolicious
C:\Strawberry\perl\site\lib\Mojolicious.pm
C:\Strawberry\perl\vendor\lib\Mojolicious.pm


whichpm -v Mojolicious
whichpm: WARNING: DUPLICATE module files found for 'Mojolicious':
  C:\Strawberry\perl\vendor\lib\Mojolicious.pm
Mojolicious     8.22    (non-core)      C:\Strawberry\perl\site\lib\Mojolicious.pm

看来问题是错误的。

重复安装的一个可能原因是模块更新不正确。安装 Strawbery 后,我使用了以下命令:

cpan-outdated -p | cpanm

谢谢大家的帮助。看起来这是一个错误的问题。我接受给定的答案并将打开一个新的 'better' 问题。

不确定 cpan 的作用,它的手册页对我来说太庞大了。它可以列出两个 Perl 版本的模块吗?或者确实安装了两个版本的模块?

这里还有一个选项,有核心ExtUtils::Installed

perl -MExtUtils::Installed -MList::Util=max -wE'
    $obj = ExtUtils::Installed->new; 
    @mods = sort $obj->modules; 
    $max_len = max map { length } @mods; 
    printf("%-${max_len}s -- %s\n", $_, $obj->version($_)) for @mods'

这将打印所有这些。要仅查看以 Mojo 开头的内容,请将最后一行更改为

/^Mojo/ and printf("%-${max_len}s -- %s\n", $_, $obj->version($_)) for @mods'

/^Mojo/ 是一个正则表达式,用于测试 $_(默认情况下)它是否以(^ 锚点)文字字符串 Mojo 开头。我认为这比使用 index 更清楚,并且是惯用的(更容易理解)。

但是printf has for the field width the length of the longest module name, found before filtering, which is likely too wide for the filtered list. So for nicer output you can first filter with grep

my @mods_filtered = sort grep { /^Mojo/ } $obj->modules; 
my $max_len = max map { length } @mods_filtered; 
printf("%-${max_len}s -- %s\n", $_, $obj->version($_)) for @mods_filtered;

所有这些都应该在一个小的实用脚本中;上面的一行用于复制粘贴测试。

有关此模块功能的详细信息,请参阅文档。

另请参阅 this post,其中包含另一个选项的代码 -- 直接搜索文件。