linux sort 명령어를 알아봅시다.

OS/리눅스 2021. 9. 28. 02:49

 안녕하세요. 이번 시간에는 리눅스 sort 명령어를 배워보면서 정렬에 대해서 간단하게 이해해 보겠습니다. man 페이지에서 언급하고 있는 로케일에 관한 warning은 이 글에서 다루지 않겠습니다. 몇 번 삽질을 해 봐야 아 로케일이 이런 거라는 것이 와 닿지 않을까 싶어요. 혹시나, 보완할 부분이나 잘못된 부분이 있다면 댓글로 남겨주시면 감사히 받겠습니다.

 


 1.in의 1번째 줄 부터 10번째 줄 까지는 이런 내용들이 있어요. 요구 사항이 하나 들어왔는데요. 공백을 기준으로 필드를 나눌 때, 1번째 필드 오름차순으로 정렬하려고 해요. 단, 필드에는 수가 있으니까, 수가 증가하는 순서대로 정렬이 되어야 합니다.

 

 

 옵션을 찾아 보니, KEYDEF라는 것이 보여요. F[.C][OPTS][,F[.C][OPTS]]가 있는데요. F가 필드 번호를 의미해요. 이것은 -k옵션과 같이 쓸 수 있습니다. k 옵션을 보겠습니다.

 

 이것은 key를 가지고 sort를 하는 건데요. KEYDEF가 위치와 type 등을 주는 걸로 보아서는, 몇 번째 필드에 대해서 정렬할 것인지에 대한 정보도 해당 옵션을 통해 준다는 것을 알 수 있어요.

 

 

 sort -k1,1은 1번째 필드를 기준으로 정렬을 한다는 의미입니다. 그런데, 결과를 보면 첫 번째에 1 0이 나오는데요. 원래 1.in은 1 99부터 시작했습니다. 그런데, 정렬하고 나서 결과의 1번째 줄부터 보니까 1 0부터 나왔는데요. 같은 우선순위를 가지는 레코드들의 순서가 뒤바뀐 것을 볼 수 있어요. 이는 stable 하지 않기 때문입니다. stable 하게 정렬하기 위해서는 -s 옵션을 붙이시면 됩니다.

 

 

 그러면 1 99가 처음부터 나오게 됩니다. stable하게 정렬을 하게 되면 여러 기준이 있을 때, 거꾸로 정렬하는 기법으로 쉽게 다중 기준 정렬을 할 수 있다는 것은 이 에서 이미 보여드렸습니다.

 


 정말 제대로 구현이 되었는지 하나의 테스트를 더 해 봅시다. 1.in의 1번째 필드에는 1 아니면 2만 들어 있었습니다. 1번째 필드에 10이 들어가는 것을 하나 넣고, sort를 시켜 보겠습니다.

 

 

 그랬더니 10 1이 2 1보다 먼저 나옴을 볼 수 있어요. 이는 수 2는 10보다 작지만 제 서버에 설정된 locale에서, 문자열 "2"는 문자열 "10"보다 뒤에 있기 때문입니다. 그러면 이 부분을 어떻게 해결하면 좋을까요? numeric sort를 하면 됩니다. 당연하게도 이 옵션이 없을 리가 없을 텐데요.

 

 

 -n 옵션을 보면, compare according to string numerical value라고 되어 있네요. 스트링 수 값에 따라서 비교한다.

 

 

 이제, -n옵션을 넣어 보면 아까와는 다르게 2가 10보다 먼저 나옴을 볼 수 있습니다. 이제, 이런 문제를 생각해 봅시다. 1번째 필드는 내림차순으로, 1번째 필드 값이 같다면 2번째 필드 오름차순으로 정렬해야 한다고 해 봅시다. 되게 복잡해 보이는데요. 사실, 이것은 역순으로 2번 sorting 하는 것으로 간단하게 할 수 있어요.

 

 2번째 필드 기준으로 먼저 오름차순으로 정렬한 다음에, 1번째 필드 기준으로 내림차순으로 정렬하면 되는데요. 아래 코드를 보겠습니다.

 

 

 -k2,2는 2번째 필드를 기준으로 정렬한다는 의미입니다. 먼저, 이 명령을 수행하고, 다음에 pipe를 이용해서 sort -k1,1 -snr 이 명령을 수행하는데요. 1번째 필드값 기준 내림차순이라 되어 있으므로, -r 옵션을 넣어서 정렬했습니다. 결과는 위와 같이 잘 나오네요. 1번째 필드가 같을 때, 2번째 필드 기준으로 오름차순으로 잘 들어갔다는 것도 볼 수 있고요.

 


 필드를 구분짓는 값이 space가 아니라 #과 같은 게 왔다면 어떨까요? --field-separator 옵션을 쓰시면 됩니다.

 

 

 설명을 보면, SEP을 쓰는데, blank transition? SEP을 정렬 과정에서 공백으로 치환하는 로직이 있나 봅니다. 이 옵션을 쓰면 구분자로 #이 있는 경우에 필드값을 잘 추출해서 sort가 가능할 겁니다.

 

 

 2.in에는 이런 데이터들이 들어 있는데요. 2#1과 10#1도 들어 있어요. 우리는, 2번째 필드 오름차순으로 정렬하려고 합니다. 그리고 각각의 필드는 수로 인식하게끔 하고요. 그럴려면, -k2,2로 2번째 필드 기준으로 정렬한다는 옵션과, -n 옵션이 들어가야 합니다. 그리고, 필드를 구분짓는 구분자가 #이므로, --field-separator=# 옵션도 들어가야 합니다.

 

 

 정렬 결과는 위와 같습니다. sort 명령어는 이 정도만 알아도 충분할 듯 싶습니다. 그 이후에는 복잡한 다중 기준 정렬을 해야 하는 경우에는 stable 옵션 붙이고 pipe를 이용해서 떨어트리는 유연한 발상을 하시면 되겠습니다. 저는 남들처럼 이런 유연함을 가지고 싶네요.