정렬이 정렬 순서를 모르는 경우 GNU 정렬 안정적인 정렬


18

2 열 파일이 있습니다. 파일은 이미 1 열에서 원하는 방식으로 정렬되었습니다. 각 열 1 범주 내에서 열 2를 정렬하고 싶습니다. 그러나 sort열 1의 정렬 순서를 이해하지 못합니다.

일반적인 방법 (스택에서 비슷한 질문으로)은 다음과 같습니다.

sort --stable -k1,1 -k2,2n

그러나 임의적이므로 k1에 정렬을 지정할 수 없습니다.

입력 예 :

C 2
C 1
A 2
A 1
B 2 
B 1

출력 :

C 1
C 2
A 1
A 2
B 1 
B 2

답변:


20

awk를 사용하여 각 블록에 대해 새로운 정렬을 시작할 수 있습니다.

% awk -v cmd="sort -k2,2" '$1 != prev {close(cmd); prev=$1} {print | cmd}' foo
C 1
C 2
A 1
A 2
B 1
B 2
  • $1 != prev {close(cmd); prev=$1} -저장된 값이 다르면 새 블록이 있으므로 이전에 시작한 모든 것을 닫습니다 sort
  • {print | "sort -k2,2"}'출력이로 sort실행되고 아직 실행되지 않은 경우 시작합니다 (awk는 시작하는 명령을 추적 할 수 있음)

2
awk는 정말로 믿어지지 않는다. 나는 이것이 내가 기대했던 것보다 훨씬 더 좋아합니다.
에반 벤

나는 이것의 성능과 다른 답변을 비교하려고했는데 왜이 리소스가 더 많은 리소스를 사용하는지 확실하지 않습니다 ... 어떤 아이디어? gist.github.com/EvanTheB/5b64eafb84eeaf51c289295ac06e1b0b
에반 벤

평균 몇 번의 달리기를 했습니까?
muru

나는 평균화하지 않았지만 반복하고 조사 할 때 일관된 런타임을보고 있습니다.
에반 벤

다음은 내가 조사하고 싶을 때 사용하고있는 것과 비슷한 파일입니다.seq 30 | xargs -L1 bash -cs 'yes $1 | head -1000000 | paste - <(seq 1000000) | shuf' bash
Evan Benn

12

Schwartzian 변환을 사용할 수 있습니다 (기본적으로 주석에서 언급 한 데코레이션-정렬-비 장식 접근법이지만 다중 호출과는 달리 단일 호출 을 사용하여 muru의 훌륭한 답변 보다 성능이 우수 sort합니다)- awk접두사 열 추가 첫 번째 열의 값이 변경되면 증분되고 접두사 열과 "두 번째"열 (순서 위치가 3접두사 열의 존재 로 인해 일시적으로 이동 된 순서)을 기준으로 정렬 한 다음 마지막으로 접두사 열을 제거합니다.

awk '{print ($1 in a? c+0: ++c)"\t" $0; a[$1]}' file | sort -k1,1n  -k3,3 | cut -f 2-

나는 놀랐지 만, 당신은 맞습니다, 이것은 다른 답변보다 빠릅니다! 1 억 개의 라인 파일에서 3 분 대 2 분 (~ 30 개의 첫 번째 열).
에반 벤

1
첫 번째 열에서 고유 키 배열을 유지할 필요가 없습니다. 현재 줄의 첫 번째 열과 이전 줄을 비교하기에 충분해야한다고 생각합니다.
Kusalananda

awk -v OFS="\t" '$1 != prev { key++ } { print key, $0; prev = $1 }(추천되지 않은) 같은 것 .
Kusalananda
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.