按TLD域排序主机文件,而不是通过后缀(.com.whatever)或前缀(子域)

时间:2017-03-22 20:20:46

标签: perl sorting unix terminal

我需要在主机文件中对超级巨大的半密码条目列表进行排序。但我想不是通过子域或.com .net对它们进行排序。

所以这个:

www.apple3.com
this.apple4.com
that.apple1.uk
and.that.apple2.com.br

将变成这个:

that.apple1.uk
and.that.apple2.com.br
www.apple3.com
this.apple4.com

此列表中没有ips(因为所有将解析为0.0.0.0,我稍后会添加)只是域名在列表中。我正在使用带有brew的Mac,所以我可以使用任何GNU或nix工具。提前谢谢!

1 个答案:

答案 0 :(得分:3)

在Perl中进行高效排序的关键是创建一个函数,该函数将值转换为可以按字典顺序排序的代表性字符串。

例如,如果要对日期进行排序,可以将它们转换为yyyymmdd格式。在这种情况下,我们将重新排序域的部分,以便

foo.bar.apple1.co.uk

成为以下之一:

# Using this approach, the sorted order of apple1.com and apple1.net will vary.
apple1.bar.foo

# Using this approach, the sorted order of apple1.com and apple1.net will be consistent.
apple1.bar.foo<NUL>uk.co

我们希望数字自然排序,(1,2,10而不是1,10,2)。我们的关键功能可以解决这个问题,但我们会从Sort::Key::Natural替换sortnatkeysort一起轻松解决问题。作为奖励,natkeysort使我们能够轻松整合我们的关键功能!

困难的部分是识别后缀。没有规则,只是不断改变定义。因此,我们将使用模块来识别后缀。

使用Domain::PublicSuffix实现密钥功能:

use feature qw( state );

use Domain::PublicSuffix qw( );

sub get_sort_key {
   my ($host) = @_;
   $host =~ s/\.\z//;
   state $dps = Domain::PublicSuffix->new();
   $dps->get_root_domain($host)
      or die "$host: ".$dps->error();

   my @name   = split /\./, substr($host, 0, -length($dps->suffix())-1);
   my @suffix = split /\./, $dps->suffix();
   return join('.', reverse @name)."\0".join('.', reverse @suffix);
}

使用IO::Socket::SSL::PublicSuffix实现密钥功能:

use feature qw( state );

use IO::Socket::SSL::PublicSuffix qw( );

sub get_sort_key {
   my ($host) = @_;
   my @host = split(/\./, $host);
   state $ps = IO::Socket::SSL::PublicSuffix->default();
   my ($name, $suffix) = $ps->public_suffix(\@host);
   return join('.', reverse @$name)."\0".join('.', reverse @$suffix);
}

以上功能如下:

use feature qw( say );

use Sort::Key::Natural qw( natkeysort );

my @hosts = (
   'www.apple3.net',
   'www.apple3.com',
   'this.apple4.com',
   'that.apple4.com',
   'www.apple10.com',
   'that.apple1.uk',
   'and.that.apple2.com.br',
);

my @sorted_hosts = natkeysort { get_sort_key($_) } @hosts;

say for @sorted_hosts;

输出:

that.apple1.uk
and.that.apple2.com.br
www.apple3.com
www.apple3.net
that.apple4.com
this.apple4.com
www.apple10.com
据推测,{p> IO::Socket::SSL::PublicSuffix的更新频率高于Domain::PublicSuffix(和Mozilla::PublicSuffix),但它是较大发行版的一部分。