>> 이중 꺾쇠 괄호를 사용하여 행을 정렬하는 방법은 무엇입니까?

>> 이중 꺾쇠 괄호를 사용하여 행을 정렬하는 방법은 무엇입니까?

sort다음과 같은 라인에서 이상하게 행동하는 것 같습니다 .>>b

$ cat test
a
>>b
b
c
>
>>

$ sort test
>
>>
a
b
>>b
c

나는 그 >>b줄이 출력의 세 번째 줄일 것이라고 예상했는데 sort다섯 번째 줄입니다. 왜 이런 일이 발생하며 sort예상되는 결과를 얻을 수 있는 방법이 있습니까 ?

저는 GNU/Linux Ubuntu 16.04를 사용하고 있습니다.

답변1

현대 언어 환경의 정렬 알고리즘은 매우 복잡합니다.

각 캐릭터(실제로는요소 구성여러 문자의 시퀀스로 구성될 수 있습니다(예: Czech ch).가중치 구성정렬 순서를 결정합니다.

두 문자열을 비교할 때 모든 문자의 첫 번째 가중치가 먼저 사용된 다음 다른 가중치를 사용하여 두 문자열이 첫 번째 가중치와 동일하게 정렬되었는지 확인합니다.

예를 들어, 많은 로케일에서 , eéE동일합니다.기초적인가중치(동일한 동등 클래스에 속하며 둘 다 일치합니다 [=e=]).

echo따라서 예를 들어 , été및 를 Enter첫 번째 패스에서 비교할 때 기본 가중치가 동일 e하고 두 번째 문자가 순서( before before )를 결정합니다.éEcnt

첫 번째 패스 이후 été, , 를 비교할 때 Été동일한 순위가 지정되므로 두 번째 패스에 2차 가중치를 적용합니다. Ete일반적인 GNU 로케일에서는 라틴어 스크립트 문자의 두 번째 가중치가 악센트의 우선순위를 결정하는 데 사용됩니다(악센트가 없는 것, 그 다음 예음, 악센트가 있는 것, 브레베, 음소거 등). 그런 다음 été합계를 결정하기 위해 세 번째 가중치를 사용해야 하며 Été이는 대소문자를 기준으로 합니다(대부분의 로케일에서는 소문자부터 시작). 심지어 체중이 동일하기 때문에 순위가 같은 캐릭터도 있습니다.

이는 인간과 마찬가지로 사전과 같은 방식으로 텍스트를 정렬하는 데 사용됩니다.

사전에서는 공백과 대부분의 구두점도 무시된다는 것을 알 수 있습니다. 예를 들어 de factodebut사이를 정렬합니다 devoid. 공백 문자의 첫 번째 가중치는 IGNORE입니다.

/usr/share/i18n/locales/iso14651_t1_commonGNU 시스템에서는 정의된 핵심 데이터 정렬을 찾을 수 있습니다(경로는 배포판에 따라 다를 수 있음). 거기에서 다음을 볼 수 있습니다:

ifdef UPPERCASE_FIRST
<CAP>
else
<MIN>
endif
[...]
ifdef UPPERCASE_FIRST
[...]
<MIN> # 10
[...]
else
[...]
<CAP> # 9
[...]
endif

[...]
order_start <SPECIAL>;forward;backward;forward;forward,position
<U0020> IGNORE;IGNORE;IGNORE;<U0020> # 32 <SP>
[...]
<U003E> IGNORE;IGNORE;IGNORE;<h> # 140 >
[...]
ifdef DIACRIT_FORWARD
order_start <LATIN>;forward;forward;forward;forward,position
else
order_start <LATIN>;forward;backward;forward;forward,position
endif
[...]
<U0065> <e>;<BAS>;<MIN>;IGNORE # 259 e
<U00E9> <e>;<ACA>;<MIN>;IGNORE # 260 é
[...]
<U0045> <e>;<BAS>;<CAP>;IGNORE # 577 E
<U00C9> <e>;<ACA>;<CAP>;IGNORE # 578 É

이것은 우리가 방금 말한 내용을 보여줍니다. 공간과 >처음 3개의 가중치는 모두 로 설정됩니다 IGNORE. 처음 3개의 가중치가 동일하게 정렬된 문자열의 경우에만 상대적 순서( >공백 앞, <h>지정되지 않은 조합 기호 앞에 나열됨 <U0020>)가 고려됩니다.

정의된 로케일 UPPERCASE_FIRST(예 /usr/share/i18n/locales/tr_TR: )에서는 대문자가 먼저 나타납니다(세 번째 패스에서 ) . DIACRIT_FORWARD일부 로케일 과 마찬가지로 de_DE두 번째 패스에서는 발음 구별 부호 의 순서를 반대로 결정할 수 있습니다 .

>패스 1, 2 , 3 에서도 동일한 정렬을 수행합니다 . 네 번째 항목에서는 문자열이 모든 항목보다 먼저 정렬되므로 먼저 정렬하세요.>>>>>

>>b그 이후에 정렬하십시오. b처음 3개 패스에서는 동일하게 정렬되었지만 b네 번째 패스에서는 무시되어 >크기가 더 크기 때문입니다. c첫 번째 패스( >무시 및 이전) b보다 적습니다 . c아이디어를 얻으실 수 있습니다.

C이제 로케일 정의를 보면 . 훨씬 간단합니다. 가중치는 하나만 있으며, U+0000부터 U+10FFFF까지의 코드 포인트 값을 기준으로 합니다. 따라서 SPC(U+0020)은 >(U+003E)보다 먼저 정렬되고, (U+003E)는 b(U+0062)보다 먼저 정렬되고, (U+0063)은 c(U+0063)보다 먼저 정렬됩니다. 어떤 캐릭터도 간과되지 않습니다.

적어도 GNU libc의 경우 비교 함수( strcoll()따라서 사용된 공동 )가 포함될 때 sortC 로케일 정의 파일에 정의된 순서가 무시됩니다 . 의 값에 관계없이 LC_CTYPE및 는 와 동일 LC_COLLATE=C합니다 . 비교는 항상 바이트 값을 기준으로 하기 때문에 해당 바이트가 유니코드 코드 포인트가 반대 방향으로 정렬된 문자에 해당하더라도(예: ISO-8859-15의 0xA4 U+20AC EURO SIGN 대 A5 U+00A5 YEN SIGN) 문자 세트) 및 ( 다르게 설정되지 않은 경우)는 동일한 효과를 갖습니다.strcoll()strcmp()LC_ALL=C sortLC_COLLATE=C sortLC_ALL

답변2

sort(1)매뉴얼 페이지 에서 :

   *** WARNING *** The locale specified by the  environment  affects  sort  order.   Set
   LC_ALL=C to get the traditional sort order that uses native byte values.

따라서 바이트 값으로 정렬하려면 다음을 사용하십시오.

LC_ALL=C sort test

그렇지 않으면 sort정렬할 수 있는 키가 발견될 때까지 선행 문자가 무시됩니다. 이것이 바로 >>bb서로 옆에 있는 이유입니다.

관련 정보