Bashから数値範囲で2つの配列を並べ替える

Bashから数値範囲で2つの配列を並べ替える

作業したい要素の数と同じ数の要素を持つ2つの配列があります。ファイルから2つの配列に読み込みます(奇数行は配列1に、偶数行は配列2に移動します)。

arr1=("1" "1" "3" "2" "4" "7" "7" "7" "1" "2" "3" "3" "3" "3" "7" "5")
arr2=("4" "1" "3" "5" "7" "1" "2" "3" "2" "9" "2" "6" "8" "9" "4" "6")

このデータは、2つのアレイの同じ場所にあるシーズンとエピソードの数を表します。したがって、配列1(arr1)はシーズン、配列2(arr2)はエピソードであり、要素番号に基づいてソートされます。等${arr1[0]}に該当します。${arr2[0]}

私がしたいのは、シーズンごとに最初に並べ替えてから、エピソード別に並べ替えることです。したがって、元の配列(どの項目がどの要素であるかコメントを含む)は次のようになります。

       1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16
arr1=("1" "1" "3" "2" "4" "7" "7" "7" "1" "2" "3" "3" "3" "3" "7" "5")
arr2=("4" "1" "3" "5" "7" "1" "2" "3" "2" "9" "2" "6" "8" "9" "4" "6")
       1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16

になる:

       2   9   1   4   10  12  3   12  13  14  5   16  6   7   8   15
arr1=("1" "1" "1" "2" "2" "3" "3" "3" "3" "3" "4" "5" "7" "7" "7" "7")
arr2=("1" "2" "4" "5" "9" "2" "3" "6" "8" "9" "7" "6" "1" "2" "3" "4")
       2   9   1   4   10  12  3   12  13  14  5   16  6   7   8   15

考えられる考え:

  1. iの各エントリに対して、対応する${arr1[@]}要素が${arr2[n]}ファイルに書き込まれます。その後、ファイルをsort実行できます。
n="0"
for i in "${arr1[@]}"; do
    echo "${arr2[${n}]}" >> "${i}.txt"
    (( n++ ))
done

しかし、私はディスクへの書き込みが含まれないようにしたいと思います(sort必要ない場合)。

  1. データを一種の別々の配列にソートしますか?各季節には独自の配列があり、同様の方法でソートできますが、sort -n "${season1Arr[@]}"これがどのように実行されるのかわかりません。

  2. データ処理方法を変更しますか?入力ファイルは変更できませんが、処理方法は変更できます。偶数/奇数行番号に基づいて、2つの配列で行を読み取るのではなく、別の方法で管理できますか?

互換性のためにできるだけ純粋なbashを維持しようとしていますが、外部プログラムを使用する必要がある可能性が高いことを知っています。どんなアイデアもありがとうございます。

ベストアンサー1

以下は、コメントで説明した例です。 Perlと連想配列(ハッシュ)を使用しますが、私が言及した自然順序(単純な数字または英数字の順序、たとえば1.10より前)の代わりにバージョン順序を使用します。 1.2、つまり「series.episode」は次のようになります。明らかに間違っています):

#!/usr/bin/perl

use strict;

use Sort::Versions;

my %data;
my ($key, $series, $episode);

while (<>) {
  chomp; # remove trailing newline from input

  if ($. % 2 == 1) {
    $series = $_;
  } else {
    $episode = $_;
    $key = "$series.$episode";
    $data{$key} = 1;
  };
}

print join(", ", sort { versioncmp($a, $b) } keys %data), "\n";

これは少し短くなるかもしれません。実際に必要な唯一の変数は、入力値の使用方法を明確にするために使用された%dataハッシュです。 BTWはデフォルトの入力/値/反復子です。これはPerlで多くの目的に使用され、他の変数が提供されていない場合は、多くの関数と構文要素がそれを使用します。このスクリプトでは、ループが読み取る現在の行の値です。 「一般変数」を表示して検索します。$series$key$episode$_while (<>)man perlvar

#!/usr/bin/perl

use strict;
use Sort::Versions;

my (%data, $series);

while (<>) {
  chomp; 

  if ($. % 2 == 1) {
    $series = $_;
  } else {
    $data{"$series.$_"} = 1;
  };
}

print join(", ", sort { versioncmp($a, $b) } keys %data), "\n";

実行例(両方のバージョンが同じ出力を生成します):

$ ./sort-series-episode.pl input.txt  
1.1, 1.2, 1.4, 1.15, 2.5, 2.9, 3.2, 3.3, 3.6, 3.8, 3.9, 4.7, 5.6, 7.1, 7.2, 7.3, 7.4

メモ:並べ替え::バ​​ージョンモジュールはコアPerlモジュールではなく、配布パッケージを介してcpan個別にインストールする必要があります。たとえば、Debianではapt-get install libsort-versions-perl

おすすめ記事