작업하려는 요소 수와 동일한 수의 요소를 가진 두 개의 배열이 있습니다. 파일에서 두 개의 배열로 읽습니다(홀수 행은 배열 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")
이 데이터는 두 어레이의 동일한 위치에 있는 시즌 및 에피소드 수를 나타냅니다. 따라서 배열 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
가능한 아이디어:
i
의 각 항목에 대해${arr1[@]}
해당 요소가${arr2[n]}
파일에 기록됩니다. 그런 다음 파일을sort
실행할 수 있습니다.
n="0"
for i in "${arr1[@]}"; do
echo "${arr2[${n}]}" >> "${i}.txt"
(( n++ ))
done
그러나 나는 디스크 쓰기가 포함되는 것을 피하고 싶습니다( sort
필요하지 않은 경우).
데이터를 일종의 별도 배열로 정렬 하시겠습니까? 각 계절에는 고유한 배열이 있으며 비슷한 방법을 사용하여 정렬할 수 있지만
sort -n "${season1Arr[@]}"
이것이 어떻게 수행되는지는 모르겠습니다.데이터 처리 방식을 변경하시겠습니까? 입력 파일을 변경할 수는 없지만 처리 방법은 변경할 수 있습니다. 짝수/홀수 라인 번호를 기반으로 라인을 두 개의 배열로 읽는 대신 다른 방법으로 관리할 수 있을까요?
호환성을 위해 가능한 한 순수한 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
답변2
perl
이런 종류의 작업에는 훨씬 더 좋지만 순수 bash에서 거의 수행할 수 있습니다(외부 사용에 안전함 ) sort
.
#!/bin/bash
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" )
# make an array with strings from both initial arrays:
arr_length=${#arr1[@]}
for ((i=0; i< $arr_length; i++)); do
arr_combined[$i]="${arr1[$i]}!${arr2[$i]}"
done
# sort the combined strings
arr_sorted=( $(printf "%s\n" "${arr_combined[@]}" | sort) )
# split the elements of sorted array back into two arrays
for pair in ${arr_sorted[@]} ; do
arr1n+="${pair%!*} "
arr2n+="${pair#*!} "
done
# print the results
printf "%s\n" "${arr1n[@]}"
printf "%s\n" "${arr2n[@]}"
답변3
원본 파일의 숫자를 먼저 정렬한 다음 배열을 채우면 작업이 더 쉬워집니다. 원본 파일에 다음과 같은 내용이 포함되어 있다고 가정합니다.
$ cat file1
1 1 3 2 4 7 7 7 1 2 3 3 3 3 7 5
4 1 3 5 7 1 2 3 2 9 2 6 8 9 4 6
따라서 이 명령은 다음과 같습니다.
transpose file1 | sort | transpose
당신이 원하는 것을 생산할 것입니다 :
1 1 1 2 2 3 3 3 3 3 4 5 7 7 7 7
1 2 4 5 9 2 3 6 8 9 7 6 1 2 3 4
조옮김 기능은 매우 간단합니다. 직접 작성하셔도 됩니다. 예는 다음과 같습니다.
transpose ()
{
awk '{ for (i=1; i<=NF; i++) a[i]= (i in a?a[i] OFS :"") $i; }
END{ for (i=1; i<=NF; i++) print a[i] }' $1
}
답변4
귀하의 설명에 따르면 다음이 원래 입력 데이터일 수 있습니다.
1
4
1
1
3
3
2
5
4
7
7
1
7
2
7
3
1
2
2
9
3
2
3
6
3
8
3
9
7
4
5
6
원하는 방식으로 이를 처리하려면 다음을 수행하십시오.
paste - - <file | sort -k 1,1n -k 2,2n
먼저 데이터를 탭으로 구분된 두 개의 열로 변환합니다. 첫 번째 열은 시즌이고 두 번째 열은 에피소드입니다.
행은 첫 번째 열에 숫자순으로 정렬되고, 첫 번째 열이 동일한 행은 두 번째 열에 숫자순으로 정렬됩니다.
위에 표시된 입력을 사용하면 다음이 생성됩니다.
1 1
1 2
1 4
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