如何在第二列中有键的文件中每 4 行对第一列进行排序

如何在第二列中有键的文件中每 4 行对第一列进行排序

示例文件:

第一列可以有固定的 4 个无序值集 world1.com,world2.com,world3.com or world4.com

第二列是属于每一行的密钥,使得四组中的每一组都有唯一的随机密钥。

world4.com           /randomkeyhghgdh778/key67567
world1.com           /randomkeygahjuh572/key639839
world2.com           /randomkey788gauh72/key63whjk
world3.com           /randomkey788gauh72/key63whjk
world1.com           /randomkeyhueh34778/key67uuu77
world4.com           /randomkey8998382/key6hh77686
world3.com           /randomkey7HHHH0000/key6333355k
world2.com           /randomkeyJJJJ1111/key63333

等等

期望的输出:

world1.com           /randomkeygahjuh572/key639839
world2.com           /randomkey788gauh72/key63whjk
world3.com           /randomkey788gauh72/key63whjk
world4.com           /randomkeyhghgdh778/key67567
world1.com           /randomkeyhueh34778/key67uuu77
world2.com           /randomkeyJJJJ1111/key63333
world3.com           /randomkey7HHHH0000/key6333355k
world4.com           /randomkey8998382/key6hh77686

答案1

按世界组织文件:

$ paste -d'\n' <(grep world1 file) <(grep world2 file) <(grep world3 file) <(grep world4 file)
world1.com           /randomkeygahjuh572/key639839
world2.com           /randomkey788gauh72/key63whjk
world3.com           /randomkey788gauh72/key63whjk
world4.com           /randomkeyhghgdh778/key67567
world1.com           /randomkeyhueh34778/key67uuu77
world2.com           /randomkeyJJJJ1111/key63333
world3.com           /randomkey7HHHH0000/key6333355k
world4.com           /randomkey8998382/key6hh77686

怎么运行的

我们可以用它grep来选择每个世界的线:

$ grep world4 file
world4.com           /randomkeyhghgdh778/key67567
world4.com           /randomkey8998382/key6hh77686

paste合并多个文件中的行。粘贴命令可能如下所示:

paste -d'\n' file1 file2 file3 file3.

我们实际上不必为每个世界创建真实的文件。相反,我们可以使用以下方法为每个对象创建类似文件的对象流程替代:

paste -d'\n' <(grep world1 file) <(grep world2 file) <(grep world3 file) <(grep world4 file)

工艺替代bash、zsh 以及 AT&T ksh88 和 ksh93 支持,但不支持 dash、pdksh 或 mksh。

额外功能:按键排序

为了说明这种方法的灵活性,我们将对每个世界的键进行排序。 注意:排序会分解多组行。如果您想将集合放在一起,请不要使用此功能。

我们可以使用 来分隔世界grep,然后使用sort每个世界,然后使用 来将这些行重新合并在一起paste

$ paste -d'\n' <(grep world1 file | sort -k2,2) <(grep world2 file | sort -k2,2) <(grep world3 file | sort -k2,2) <(grep world4 file | sort -k2,2)
world1.com           /randomkeygahjuh572/key639839
world2.com           /randomkey788gauh72/key63whjk
world3.com           /randomkey788gauh72/key63whjk
world4.com           /randomkey8998382/key6hh77686
world1.com           /randomkeyhueh34778/key67uuu77
world2.com           /randomkeyJJJJ1111/key63333
world3.com           /randomkey7HHHH0000/key6333355k
world4.com           /randomkeyhghgdh778/key67567

请注意,这sort取决于区域设置。不同locales可能会导致不同的顺序。

答案2

#!/usr/bin/perl
use strict;
use warnings;

use autodie;
use open qw< :encoding(ASCII) >;

my $filename = $ARGV[0];
my ($ip_fh, $op_fh);
open($ip_fh, "<", $filename);
open($op_fh, ">", "$filename".".sorted");
my @ip_lines = <$ip_fh>;

for(my $i = 0; $i <= $#ip_lines; $i++)
{
    print $op_fh sort @ip_lines[$i..($i+3)];
    $i += 3;
}

close($ip_fh);
close($op_fh);

给出输入文件名作为命令行参数,例如:

./sort_blocks.pl data.txt

答案3

perl脚本应适用于任意数量的域(第一个字段),每个域具有任意数量的键(第二个字段)。域名可能每个都有相同数量的密钥,但不是必须的。

它构建一个散列 ( %domains),散列的每个元素都包含一个键数组。在此过程中,它会跟踪任何域中看到的最大数量的密钥。

读取所有输入后,它会打印每个域存在的每个密钥。

#! /usr/bin/perl

use strict;
use warnings;

my %domains = ();
my $numkeys = 0;

while(<>) {
  chomp;
  my ($domain, $key) = split;
  push @{ $domains{$domain} }, $key;

  # find the largest number of keys for any domain
  $numkeys = scalar @{ $domains{$domain} } if (scalar @{ $domains{$domain} } gt $numkeys);
}

for my $keynum (0..$numkeys-1){
    foreach my $domain (sort keys %domains) {
        print "$domain\t$domains{$domain}[$keynum]\n" if (defined($domains{$domain}[$keynum]));
    }
}

输出:

world1.com  /randomkeygahjuh572/key639839
world2.com  /randomkey788gauh72/key63whjk
world3.com  /randomkey788gauh72/key63whjk
world4.com  /randomkeyhghgdh778/key67567
world1.com  /randomkeyhueh34778/key67uuu77
world2.com  /randomkeyJJJJ1111/key63333
world3.com  /randomkey7HHHH0000/key6333355k
world4.com  /randomkey8998382/key6hh77686

如果没有相同数量的键被视为错误,请将print "$domain\.....最后一个代码块中的行替换为:

if (defined($domains{$domain}[$keynum])) {
    print "$domain\t$domains{$domain}[$keynum]\n"
} else {
    warn "$domain is missing a key\n";
};

如果您希望这是一个致命错误,请替换warn为。die

答案4

在 GNU 系统上:

$ NL='
'
$ <file xargs -n4 -d "$NL" sh -c 'printf "%s\n" "$@" | sort' sh
world1.com           /randomkeygahjuh572/key639839
world2.com           /randomkey788gauh72/key63whjk
world3.com           /randomkey788gauh72/key63whjk
world4.com           /randomkeyhghgdh778/key67567
world1.com           /randomkeyhueh34778/key67uuu77
world2.com           /randomkeyJJJJ1111/key63333
world3.com           /randomkey7HHHH0000/key6333355k
world4.com           /randomkey8998382/key6hh77686

如果您的 shell 支持,您可以使用$'\n'代替。"$NL"

相关内容