次の質問があります。いくつかの値を含む配列がありますarr
。各値を異なる宣言された配列のセット、earr$j
つまりarr[0]
into earr1
、arr[1]
into、earr2
および通常はarr[j-1]
intoでソートしたいと思いますearr$j
。 (後でsと同じ要素をtarget sの次の要素arr
として追加します)。earr$j
私は次のコードスニペット(より大きなコードスニペットの一部)を使用してこれを実行しようとしています。
for j in $(seq 1 $number_of_elements); do earr$j+=(${arr[j-1]}); done
私が作るようだと言われました(私の記事「https://unix.stackexchange.com/questions/675454/for-loop-and-appending-over-list-of-arrays」を参照)。 2次元配列(Bashではサポートされていません)私は、Bash構文を不適切に使用した結果に関係なく、これが私の意図ではないことを強調します。以前の投稿でこの問題を正しく説明していないため、再公開します。
答え1
質問に文字通り答えるには、通常、次のように機能しますeval
。
for i in "${!arr[@]}"; do
eval '
earr'"$i"'+=( "${arr[i]}" )
'
done
eval
危険ですが、正しく使用すると安全です。エラーのリスクを制限する良い方法は、確実に拡張が必要な部分を除いて、すべてを一重引用符で囲み、一重引用符の内側にない部分を確認すること$i
です。変数のi
)は完全にあなたの制御下にあります。この場合、$i
数字のみが含まれることがわかっているため、これはeval
シェルコードで評価される任意のデータではありません(逆に一重引用符を${arr[i]}
省略したくありません)。
なぜ二次元配列が不適切だと言われるのか、まだ理解されていません。ksh93
(bash
ksh93の構文のほとんどをコピーしましたが、多次元配列はコピーしません)から、次のことができます。
for i in "${!arr[@]}"; do
earr[i]+=( "${arr[i]}" )
done
とにかくシェルを使用する特別な理由がない場合は、@casの言葉に同意しますperl
。python
。
答え2
以下は、Perl および HoAoA (Hash of Arrays) データ構造を使用して説明するタスクを実行する方法の例です。
これを理解するのに役立つように、次のマニュアルページが役に立ちます:perldata
(perlデータ型)、 perldsc
(データ構造)、perllol
(lol =リストリスト)、perlref
(参照資料)、perlreftut
(参照チュートリアル)あるいはperldoc
、同じコマンドを使用してperldoc -f opendir
特定のPerl機能に関する詳細情報を取得することもできますperldoc -f grep
。
スクリプトで使用されたsort
合計はgrep
組み込みのPerl関数であることに注意してください。彼らいいえsort
コマンドラインツールgrep
...必要に応じて、Perlからこれらのツールを呼び出すことができます(バックティック、引用符qx
、関数、system()
またはopen()
パイプを開く関数を使用するなど、いくつかの方法を使用します)。これらすべてとそれ以上の詳細を確認してくださいperldoc
。
$ cat HoAoA.pl
#!/usr/bin/perl
use strict;
use Data::Dump qw(dd);
# $h is a ref to Hash-of-Array-ofArrays (HoAoA).
#
# This will be a data structure with the directory names
# (Folder1, Folder2, Folder3) as the hash keys of the top-level
# hash. Each element of that hash will be an array where the
# indexes are the line numbers of the data.txt files in each
# of those directories. The data in these second-level arrays
# will be an array containing the three values in each line of
# data.txt: $$h{directory}[line number][element]
my $h;
# get the directory name from the first command line arg, default to ./
my $dir = shift // './';
# get a list of subdirectories that contain 'data.txt',
# excluding . and ..
opendir(my $dh, "$dir") || die "Couldn't open directory $dir: $!\n";
my @dirs = sort grep { $_ !~ /^\.+$/ && -d $_ && -f "$_/data.txt" } readdir($dh);
closedir($dh);
dd \@dirs; # Data::Dump's dd function is great for showing what's in an array
print "\n";
foreach my $d (@dirs) {
my $f = "$d/data.txt";
open(my $fh,"<",$f) || die "Couldn't open file $f: $!\n";
my $lc=0; # line counter
while(<$fh>) {
chomp; # strip trailing newline char at end-of-line
my @row = split /\s*,\s*/; # assume simple comma-delimited values
push @{ $$h{$d}[$lc++] }, @row;
}
close($fh);
}
# dd is even better for showing complex structured data
dd $h;
print "\n";
# show how to access individual elements, e.g. by changing the
# zeroth element of line 0 of 'Folder1' to 999.
$$h{'Folder1'}[0][0] = 999;
dd $h;
print "\n";
# show how to print the data without using Data::Dump
# a loop like this can also be used to process the data.
# You could also process the data in the main loop above
# as the data is being read in.
foreach my $d (sort keys %{ $h }) { # `foreach my $d (@dirs)` would work too
print "$d/data.txt:\n";
foreach my $lc (keys @{ $$h{$d} }) {
print " line $lc: ", join("\t",@{ $$h{$d}[$lc] }), "\n";
}
print "\n";
}
注:上記は、単純なカンマ区切りデータファイルを処理するために作成されました。すべての特異性と複雑さ(たとえば、カンマを含む複数行の二重引用符フィールド)を持つ実際のCSVの場合は、次のようにします。テキスト::CSV基準寸法。これは、コアPerlディストリビューションに含まれていないサードパーティのライブラリモジュールです。 Debianおよび関連ディストリビューションではapt-get install libtext-csv-perl libtext-csv-xs-perl
。またはcpan
(perlコアに含まれているライブラリモジュールのインストールおよび管理ツール)を使用してインストールすることもできます。
また注:上記のスクリプトはデータ::ダンプ。これは、構造化データをダンプするために使用できるサードパーティのモジュールです。残念ながら、Perlコアライブラリには含まれていません。 Debianapt-get install libdata-dump-perl
などの他のディストリビューションも同様のパッケージ名を持っています。そして最後の手段としてcpan
。
とにかく、次のフォルダ構造とdata.txtファイルを使用します。
$ tail */data.txt
==> Folder1/data.txt <==
1,2,3
4,5,6
7,8,9
==> Folder2/data.txt <==
7,8,9
4,5,6
1,2,3
==> Folder3/data.txt <==
9,8,7
6,5,4
3,2,1
HoHoA.pl スクリプトを実行すると、次の出力が生成されます。
$ ./HoAoA.pl
["Folder1", "Folder2", "Folder3"]
{
Folder1 => [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
Folder2 => [[7, 8, 9], [4, 5, 6], [1, 2, 3]],
Folder3 => [[9, 8, 7], [6, 5, 4], [3, 2, 1]],
}
{
Folder1 => [[999, 2, 3], [4, 5, 6], [7, 8, 9]],
Folder2 => [[7, 8, 9], [4, 5, 6], [1, 2, 3]],
Folder3 => [[9, 8, 7], [6, 5, 4], [3, 2, 1]],
}
Folder1/data.txt:
line 0: 999 2 3
line 1: 4 5 6
line 2: 7 8 9
Folder2/data.txt:
line 0: 7 8 9
line 1: 4 5 6
line 2: 1 2 3
Folder3/data.txt:
line 0: 9 8 7
line 1: 6 5 4
line 2: 3 2 1