我想要具有不同版本的软件列表。例如,除了最后两个之外的所有版本都有不同的版本。订单可能不同。
我不知道该怎么办。
答案 0 :(得分:3)
我认为Borodin通过对你的问题的评论让我走上了正确的方向:你展示的文件似乎是rpm -qa
的输出。
样品:
$ rpm -qa | head -5
aaa_skel-2006.5.19-0.3
glibc-i18ndata-2.4-31.30
release-notes-sles-10-43.51
sles-stor_evms_en-10.1-0.10
yast2-schema-2.13.5-0.13
有一些rpm
的开关会影响该输出,即--queryformat
选项。有关详细信息,请参阅此处http://www.rpm.org/max-rpm/s1-rpm-query-parts.html(向下滚动到"标记"部分)。
使用该开关,可以定义输出格式,并使用自定义字符串分隔包名称,版本和版本号:
$ rpm -qa --queryformat '%{NAME}\t%{VERSION}\t%{RELEASE}\n' | head -5
aaa_skel 2006.5.19 0.3
glibc-i18ndata 2.4 31.30
release-notes-sles 10 43.51
sles-stor_evms_en 10.1 0.10
yast2-schema 2.13.5 0.13
我在这里使用了一个标签\t
,但任何其他独特的字符/字符串都可以使用。
如果您可以通过这种方式重新编写文件列表,那么远更容易区分名称和数字,因为简单split(/\t/)
会这样做。< / p>
我知道这不是您问题的完整答案,但如果您能确定rpm -qa --queryformat
是否适合您,我会修改它。
如果我完全错了,请告诉我,我将删除我的帖子。
答案 1 :(得分:1)
这是我快速放在一起的东西,至少应该给你一个起点。我欺骗了像"Ramzi"
这样不太容易解析的条目。
请注意,如果您有非常大的文件,您可能需要采用不同的方法,因为第一个文件完全插入内存。
utempter-32bit-9-200407011229
输出:
use warnings;
use strict;
open my $fh1, '<', 'f1.txt' or die $!;
open my $fh2, '<', 'f2.txt' or die $!;
my %f1;
while (<$fh1>){
chomp;
next if ! check($_);
my ($app, $ver) = separate($_);
next if ! $app;
$f1{$app} = $ver;
}
while (<$fh2>){
chomp;
next if ! check($_);
my ($app, $ver) = separate($_);
next if ! $app;
if (exists $f1{$app}){
if ($ver ne $f1{$app}){
print "$app version differs\n";
}
}
}
sub separate {
my $line = shift;
if (my ($app, $ver) = $line =~ /(.*?)-(\d+\..*)/){
return ($app, $ver);
}
}
sub check {
my $line = shift;
if ($line !~ /\./){
print "* can't parse $line, check manually\n";
return 0;
}
return 1;
}
答案 2 :(得分:1)
这个程序似乎可以满足您的需求
将软件名称与其版本号分开是任意的,因此最好的猜测是我使用了仅包含十进制数字和点.
作为版本号的所有字段,以及之前的所有内容作为名称< / p>
use strict;
use warnings 'all';
use Sort::Naturally 'ncmp';
my @files = qw/ file1.txt file2.txt /;
my @info = map { read_file_info($_) } @files;
my @software = do {
my %sw;
++$sw{$_} for map { keys %$_ } @info;
sort keys %sw;
};
for my $sw ( @software ) {
print "$sw:\n";
my @versions = map { $_->{$sw} // '' } @info;
if ( $versions[0] eq $versions[1] ) {
printf " Version %s in both files\n", $versions[0];
}
else {
for my $i ( sort { ncmp($versions[$a], $versions[$b]) } 0 .. $#files ) {
printf " %s in %s\n",
$versions[$i] ? "Version $versions[$i]" : "Doesn't appear",
$files[$i];
}
}
print "\n";
}
sub read_file_info {
my ($file) = @_;
use autodie;
open my $fh, '<', $file;
my %info;
while ( my $line = <$fh> ) {
next unless /\S/;
my ( $software, $version ) = split_name_vn($line);
$info{$software} = $version;
}
\%info;
}
sub split_name_vn {
my ($s) = @_;
return ( $1, $2 ) if $s =~ /^(.+?)-([\d.-]+)$/;
return;
}
apache2-devel:
Version 2.0.59-5.2 in file1.txt
Version 2.2.12-1.38.2 in file2.txt
apache2-doc:
Version 2.0.59-5.2 in file1.txt
Version 2.2.12-1.40.1 in file2.txt
apache2-example-pages:
Version 2.0.59-5.2 in file1.txt
Version 2.2.12-1.40.1 in file2.txt
apache2-mod_perl:
Version 2.0.3.99-1.1 in file1.txt
Version 2.0.4-40.19 in file2.txt
apache2-prefork:
Version 2.0.59-5.2 in both files
apache2-worker:
Version 2.0.59-5.2 in both files
utempter-32bit:
Version 0.5.5-106.20.1 in file2.txt
Version 9-200407011229 in file1.txt
答案 3 :(得分:0)
$ cat tst.awk
match($0,/[-0-9.]+$/) {
pkg = substr($0,1,RSTART-1)
ver = substr($0,RSTART+1)
}
NR==FNR { p2v[pkg]=ver; next }
ver != p2v[pkg]
$ awk -f tst.awk file1 file2
apache2-devel-2.2.12-1.38.2
apache2-doc-2.2.12-1.40.1
apache2-example-pages-2.2.12-1.40.1
apache2-mod_perl-2.0.4-40.19
utempter-32bit-0.5.5-106.20.1