2番目の列のキーを使用してファイルの4行ごとに最初の列をソートする方法

2番目の列のキーを使用してファイルの4行ごとに最初の列をソートする方法

サンプルファイル:

最初の列には次のものがあります。順序付けされていない4つの値で構成される固定セット world1.com,world2.com,world3.com or world4.com

2番目の列は各行に属するキーであるため、4つのグループのそれぞれには一意のランダムキーがあります。

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は、ドメインごとのキー数(2番目のフィールド)を使用してドメイン数(最初のフィールド)に対して機能する必要があります。ドメイン名可能それぞれに同じ数のキーがありますが、必須ではありません。

%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

シェルがそれをサポートしている場合は、代わりに使用できます$'\n'"$NL"

関連情報