다음과 같은 파일이 있습니다 df
.
1 4
1 6
1 7
1 10
2 3
2 9
2 10
3 4
4 7
9 10
df의 각 행에 이러한 값 중 적어도 하나가 포함되도록 가장 작은 값 집합을 결정해야 합니다.
위에서 df
기대하는 바는 out
다음과 같습니다.
1
2
4
9
작동하는 프로세스가 있지만 매우 느립니다. 이 작업을 더 빠르게 수행하거나 프로세스를 병렬화할 수 있는 방법이 있습니까?
x=1
while [ $x -gt 0 ]
do
i=$(paste df | tr '\t' '\n' | sort | uniq -c |
sort -r -k1,1 -k2,2n | awk 'NR==1{print $2}')
echo $i >> out
grep -vw $i df > tmpdf
cat tmpdf > df
x=$(paste df | wc -l)
done
답변1
다음은 "라인 노이즈" Perl입니다.
perl -lane '
for $f (@F) {push @{$x{$f}}, $.} # 1.
} END {
use List::Util qw/any first/;
sub sort_by_count_desc {
map { $_->[0] }
sort { $b->[1] <=> $a->[1] || $a->[0] <=> $b->[0] }
map { [$_, scalar(@{$x{$_}})] }
@_
}
@ordered = sort_by_count_desc(keys %x); # 2.
%result = ();
for ($i=1; $i<=$.; $i++) { # 3.
$node = first { any {$_ == $i} @{$x{$_}} } @ordered; # 4.
$result{$node} = 1;
}
print join "\n", sort_by_count_desc(keys %result);
' df
어디
- 파일의 행을 반복하고 각 값을 해당 값이 나타나는 행 목록에 매핑합니다.
- 모양 목록 크기에 따라 내림차순으로 정렬된 값의 정렬된 행을 생성합니다.
- 줄 번호 범위와 foreach 줄 번호를 반복합니다.
- 행 번호가 나타나는 첫 번째 값 찾기
이 출력
1
2
4
10
답변2
이건 "멍청이"리눅스최적화에 사용 bash
하지만 특별히 이식성이 없으며 알고리즘을 개선하지 않습니다.
f=$(mktemp) ; cp df $f
while [ -s $f ] ; do
tr '\t' '\n' < $f | sort | uniq -c | sort -r -k1,1 -k2,2n |
grep -om1 '\S$' | tee >(grep -vwf - $f | sponge $f)
done
rm $f
노트:
사용df입력 파일을 스크래치 패드로 사용하는 것은 좋지 않습니다
mktemp
. 대신 이것을 사용하십시오.출력은 다음과 같습니다.표준 출력. 필요한 경우 로 변경합니다
done
.done > out
이것
sponge
util에는 더 이상 이름을 지정할 필요가 없습니다.tmpdf문서.검색 문자열 변수 대신
tee
및를 사용합니다 .grep -f -
$i
wc -l
있는지 확인해보세요0충분하지 않습니다test -s
.