저는 Ubuntu 18.04와 기본 coreutils를 사용하고 있습니다. 이 명령의 특이한 동작을 발견했는데 sort
어떻게 설명해야 할지 모르겠습니다.
다음 명령을 고려하십시오.
$ cat <<EOF | sort
0-
01-
EOF
0-
01-
-
이 출력은 ASCII 값이 예상보다 작기 때문에 의미가 있으며 1
따라서 이 출력이 예상됩니다.
그러나 끝에 문자를 하나 더 추가하면 다음과 같습니다.
$ cat <<EOF | sort
0-T
01-T
EOF
01-T
0-T
0-T
이 출력은 그것이 먼저 나와야 한다고 생각하기 때문에 나에게는 아무런 의미가 없습니다 . 왜 이런 일이 발생합니까? 내가 여기서 무엇을 놓치고 있는 걸까요? 내 기대가 잘못된 걸까?
답변1
이는 해당 지역의 데이터 정렬에 따라 다릅니다.
대조 순서는 악센트 부호가 있는 문자의 순서를 허용하는 각 로케일의 규칙 세트입니다(예를 들어 스페인어에서는 ñ
뒤에 표시 되고 n
앞에 표시됩니다 o
).
하지만 그렇지 않습니다. 대조 규칙에 따라 정렬 시 무시되는 문자도 지정됩니다. 로케일 "C"의 경우 모든 문자가 고려되지만 "en_US"의 경우 대시(U002D)는 무시됩니다. 대부분의 다른 로케일은 iso14651_t1_common 정의를 상속하기 때문입니다(일부 배포판에서는 /usr/share/i18n/locales /에 있음).
따라서 첫 번째 파일을 정렬해도 문제가 발생하지 않습니다. 대시를 무시하면 간단한 문자 비교로 끝나기 때문입니다.
-- ignore dashes --> -- sort -->
0- 0 0
01- 01 01
"T"를 추가하자 상황이 달라졌습니다. 이유는 무엇입니까? 이제 대시를 무시하면 "1"과 "T"(첫 번째 문자는 동일함)를 비교해야 하고 "1"이 "T" 앞에 오기 때문입니다.
-- ignore dashes --> -- sort -->
0-T 0T 01T
01-T 01T 0T
따라서 정렬 시 항상 "C" 규칙을 사용하고 LC_COLLATE=C를 사용하는 것이 가장 좋습니다.
귀하의 경우:
$ cat <<EOF | LC_COLLATE=C sort
0-T
01-T
EOF
생산하다:
0-T
01-T
예상대로.
답변2
예, 짜증나는 것처럼 보일 수도 있습니다. (기본 로케일은 en_US.UTF-8입니다)
$ printf '%s\n' 1 1- 1-a 11- 11-a | sort
1
1-
11-
11-a
1-a
그 이유는 조합 순서가 -
할당 되었기 때문입니다 no weight
.
a가 해야 할 일과 비슷한 것 "
:
printf '%s\n' 1 \"1\" 1- \"1-\" 1-a \"1-a\" 11- \"11-\" 11-a \"11-a\" | sort
"1"
"1-"
1
1-
"11-"
11-
"11-a"
11-a
"1-a"
1-a
위에서 볼 수 있듯이 모든 1은 11
물론 all도 함께 정렬됩니다. 문제는 다음과 같이 1-a
정렬된다는 것입니다 1a
.
printf '%s\n' 1-a 1-b 1-c 1a 1b 1c| sort
1-a
1a
1-b
1b
1-c
1c
~에 관계없이구두( -
및 기타) "
를 ;
데이터 정렬에 포함해야 하는지 여부는 논란의 여지가 있습니다. 일반적인 견해는 (ASCII가 아닌 로케일에서는) 그렇게 하면 안 된다는 것입니다.
이것흔한대부분의 라틴어 언어에 대한 파일은 입니다 /usr/share/i18n/locales/iso14651_t1_common
. 해당 파일에서 HYPHEN-MINUS
(예, 일반인의 용어로는 dash.Unicode U-002D라고 합니다) 정렬 순서는 다음과 같이 설정됩니다.
<U002D> IGNORE;IGNORE;IGNORE;<U002D> % HYPHEN-MINUS
즉, 처음 세 가지 마무리 수준을 무시합니다.