Regex 如何在perl中使用split函数来完成awk的工作
我正在用perl编写一个脚本,我希望尽可能避免使用外部命令,如awk、tr等。 这是我在脚本内部使用反勾号运行的命令:Regex 如何在perl中使用split函数来完成awk的工作,regex,perl,awk,Regex,Perl,Awk,我正在用perl编写一个脚本,我希望尽可能避免使用外部命令,如awk、tr等。 这是我在脚本内部使用反勾号运行的命令: my @arr = `$cmd | tr " " "\n" | xargs -n1 host | awk '{print $4}'` 这是带有outawk'{print 4$}的输出: $fileserver has address 10.90.207.59 $fileserver has address 10.90.207.34 $fileserver has addres
my @arr = `$cmd | tr " " "\n" | xargs -n1 host | awk '{print $4}'`
这是带有outawk'{print 4$}
的输出:
$fileserver has address 10.90.207.59
$fileserver has address 10.90.207.34
$fileserver has address 10.90.207.56
$fileserver has address 10.90.207.67
这是带有awk'{print 4$}
的输出:
10.90.207.59
10.90.207.34
10.90.207.56
10.90.207.67
我希望每个IP都位于阵列中一个单独的单元中。
如何当前使用perl函数(可能是split或map),而不是简单地使用awk和tr?。默认情况下,
split
的工作原理与awk
类似。因此:
my @arr = split;
print $arr[3]; #note - arrays start at zero.
然而,perl通常也可以在文件句柄上逐行运行,并且拆分
会得到您不想要的东西
您可以:
#!/usr/bin/perl
use strict;
use warnings;
while (<DATA>) {
my ($ip) = (split)[3];
print $ip, "\n";
#or push it.
}
__DATA__
$fileserver has address 10.90.207.59
$fileserver has address 10.90.207.34
$fileserver has address 10.90.207.56
$fileserver has address 10.90.207.67
#/usr/bin/perl
严格使用;
使用警告;
而(){
我的($ip)=(分割)[3];
打印$ip,“\n”;
#或者推它。
}
__资料__
$fileserver的地址为10.90.207.59
$fileserver的地址为10.90.207.34
$fileserver的地址为10.90.207.56
$fileserver的地址为10.90.207.67
但是如果你想找一件东西:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my @ips = map { (split)[3] } <DATA>;
print Dumper \@ips;
__DATA__
$fileserver has address 10.90.207.59
$fileserver has address 10.90.207.34
$fileserver has address 10.90.207.56
$fileserver has address 10.90.207.67
#/usr/bin/perl
严格使用;
使用警告;
使用数据::转储程序;
my@ips=map{(split)[3]};
打印转储程序\@ips;
__资料__
$fileserver的地址为10.90.207.59
$fileserver的地址为10.90.207.34
$fileserver的地址为10.90.207.56
$fileserver的地址为10.90.207.67
我们在列表上下文中阅读
,因此它返回整个内容-一次一个元素进行映射
然后在
映射中
我们将每个元素拆分,并抓取元素3
($4
,以awk术语) 用于类似的perl一行程序
perl -nae 'print "$F[3]\n"' input.txt
-n
对文件进行循环
-a
自动拆分模式。默认情况下,使用空格分割。存储在@F
中的输出。所以我使用第三个索引来打印ip地址。在perl索引中,从0开始,如果知道所需字段是最后一列,则可以使用从末尾向后计数的索引:
my $ip = (split)[-1];
在单行程序的情况下,使用-a
开关使Perl将行拆分为@F
数组(-n
将while(){…}
围绕-e
的参数进行包装,-l
为每个打印添加新行(请参阅)):
然而,由于您没有被awk困住,所以不必这样做。您可能可以在Perl中完成大部分工作,而无需管道。以下是您开始的内容:
my @arr = `$cmd | tr " " "\n" | xargs -n1 host | awk '{print $4}'`
它看起来像是$cmd
在一行中生成一组主机名。使用tr
将空格转换为换行符,然后在每行上运行host
。对于每个主机
输出,您获取地址
您可以在单个Perl程序中完成此操作:
use v5.24;
use Socket; # core module
use Net::hostent; # core module
my $cmd = ...;
foreach my $host ( `$cmd` ) {
chomp( $host );
my @addresses =
map { inet_ntoa($_) }
gethostbyname($host)->addr_list->@*;
say join "\n", @addresses;
}
使用列表上下文中的倒勾,Perl将命令的输出分成几行。Perl附带了核心模块和
我已经使用了v5.24的非常好的特性,->@*
,它将数组引用从addr\u list
转换为map
可以使用的常规列表
无论您在$cmd
中输入什么,都需要小心。我在本书的“安全”一章中详细讨论了这一点。您还可以在文档中找到一些内容。借助模块中的inet\u aton
和inet\u ntoa
,您可以非常简单地用Perl完成整个过程,除了$cmd
之外,因为您没有告诉我们这是什么
看起来您的$cmd
返回一行或多行主机名,以空格分隔,因此我在这里使用了echo
命令来模拟它。我还使用了Data::Dump
来显示@地址的最终内容
use strict;
use warnings 'all';
use Socket;
my $cmd = 'echo www.amazon.co.uk www.perl.com www.stackoverflow.com';
my $cmd_output = `$cmd`;
my @addresses = map { name_to_ip($_) } split ' ', $cmd_output;
use Data::Dump;
dd \@addresses;
sub name_to_ip {
my ($name) = @_;
my $add32 = inet_aton($name) or die qq{Unable to convert host name "$name": $!\n};
inet_ntoa($add32);
}
输出
输入和期望的输出?地址总是IPv4吗?太好了,谢谢,关于“tr”命令,我能做些什么吗?是的。但我不会这样做,因为这一位正在使用xargs
运行多个命令,而我只是在perl
中一次运行一个命令。同样感谢您!非常感谢您的详细回答!
use strict;
use warnings 'all';
use Socket;
my $cmd = 'echo www.amazon.co.uk www.perl.com www.stackoverflow.com';
my $cmd_output = `$cmd`;
my @addresses = map { name_to_ip($_) } split ' ', $cmd_output;
use Data::Dump;
dd \@addresses;
sub name_to_ip {
my ($name) = @_;
my $add32 = inet_aton($name) or die qq{Unable to convert host name "$name": $!\n};
inet_ntoa($add32);
}
["54.239.36.155", "207.171.7.72", "151.101.193.69"]