오늘 포스팅에서는 Linux sort 명령어의 사용 방법에 대해 알아보려 합니다.

 

아래 포스팅에서 텍스트 파일의 내용을 unique 하게 sorting 하는 방법에 대해 설명 드린적이 있는데~

 

아래 포스팅 에서는 Gow의 uniq 명령과 윈도우의 sort명령을 사용했었습니다.


2014/05/14 - [컴퓨터일반] - windows console 에서 텍스트 파일 내용 unique 하게 정렬하기

 

하지만 Linux 의 sort 명령어에는 굉장히 편리하게도 unique 옵션이 있더군요.

 

간단한 예로 다음과 같은 테스트 쿼리를 예로 들어보죠~

 

아래 insert 구문은 아래 포스팅에서 소개 드렸던 generateda를 사용하여 만들어진 테스트 데이터 입니다.


2014/06/17 - [유틸] - Database 테스트 데이터 생성 사이트 generatedata


INSERT INTO myTable (NAME,PHONE,NUMBER) VALUES ("Ahmed","1-156-444-1052",5);

INSERT INTO myTable (NAME,PHONE,NUMBER) VALUES ("Nissim","1-786-558-9774",2);

INSERT INTO myTable (NAME,PHONE,NUMBER) VALUES ("Herman","1-831-439-1058",4);

INSERT INTO myTable (NAME,PHONE,NUMBER) VALUES ("Nissim","1-144-592-7170",1);

INSERT INTO myTable (NAME,PHONE,NUMBER) VALUES ("Gannon","1-863-622-1551",4);

INSERT INTO myTable (NAME,PHONE,NUMBER) VALUES ("Samuel","1-963-369-2263",5);

 

generateda에서 랜덤하게 만들어진 데이터 이므로 중복이 있을수도 있겠죠~ 위에 예로 든 데이터에서는 Nissim 이라는 이름이 중복입니다.

 

위 예처럼 몇 줄 안 되는 경우에는 일일이 확인해서 중복되는 데이터들을 지워 줄 수 있겠지만,중복되는 경우가 많다면 일일이 사람이 지워주기는 힘들겠죠~

 

Linux 의 sort 명령어를 몰랐다면 Excel 과 같은 프로그램등을 이용해서 정렬해서 중복되는 데이터들을 제거 했겠지만 대단히 불편했을 것 같네요~

 

Sort 명령어의 몇 가지 옵션에 대해 알아보겠습니다. 저는 현재 windows 환경이라 Cygwin 에서 linux sort 함수를 사용하도록 하겠습니다.

 

-u : unique 옵션

-t : 뒤에 구분자를 넣어 줌

-k : 뒤에 몇 번째 열을 기준으로 sort 할 것인지를 넣어줌, 쉼표로 구분하여 시작열, 끝열을 넣어줌, 시작열만 지정할 경우 시작열부터 줄의 끝까지임

 

 

 

위 옵션을 바탕으로 위에서 소개한 쿼리 예에 대해 이름에 따른 정렬을 시켜 보죠~ 위 쿼리는 query.txt 파일에 적혀 있습니다.

 

위 쿼리 문자열을 보면 쌍따옴표(") 를 기준으로 2번째 열이 바로 이름 컬럼이라는 것을 알 수있습니다. 따라서 구분자로는 –t 옵션에 쌍따옴표를 넣어주고~ –k 옵션에는 2를 넣어 줍니다. 하지만 그냥 2를 넣어주면 2 부터~ 끝까지 이기 때문에~ 정상적으로 unique 하게 sort 가 안됩니다. 딱 2번째 컬럼 즉 이름 부분만 선택하기 위해 2,2 라고 넣어줘야 합니다.

 

sort –u –k 2,2 –t '"' query.txt > uniq.txt

 

 

위 명령을 실행해 보겠습니다. 다음과 같이 중복된 이름이었던 4번째 행이 사라진 것을 확인 할 수 있습니다.

 

프로그래밍을 배우면서 아마도 가장 처음 접하게 되는 알고리즘이 바로 정렬 알고리즘이 아닌가 생각되네요.

 

C++ 에서는 algorithm 헤더에 sort, stable_sort, partial_sort 와 같은 함수들이 정의되어 있습니다.

 

C++ STL 이 참 좋긴 하더군요. ㅋㅋㅋㅋ

 

partial_sort 는 말 그대로 일부를 정렬하겠다는 거로 이해하시면 될 것 같고

 

저는 처음에 sort 와 stable_sort 가 좀 헷갈리더군요. 무슨 차이일까… 하고요.

 

차이는 간단한데요. 동일한 값이 있을 경우 stable_sort 의 경우에는 정렬 하기 전의 순서가 정렬후에도 유지된다고 하더군요.

 

위 함수들의 사용법 등에 대해서는 아래 주소의 예제들을 참조하시면 쉽게 이해하실 겁니다.

 

http://www.cplusplus.com/reference/algorithm/sort/

http://www.cplusplus.com/reference/algorithm/stable_sort/

http://www.cplusplus.com/reference/algorithm/partial_sort/

 

저는 오늘 MATLAB 의 sort() 결과와 마찬가지로 정렬 결과 뿐만 아니라 인덱스도 정렬되어 나올 수 있도록 구성해 보도록 하겠습니다.

 

C++ 에서는 이런 경우 인덱스와 값을 pair 로 묶은 후에 정렬하는 방법이 있더군요.

 

예제는 다음과 같습니다. 아래 예제처럼 comparator 만 오름 차순 내림 차순에 따라 잘 설정하면 되더군요.

 

#include <iostream>

#include <vector>

#include <algorithm>

#include <random>

#include <ctime>

 

 

using namespace std;

 

 

#define N_SIZE (10)

 

 

typedef std::pair<int,int> int_int_pair;

 

bool comparator ( const int_int_pair& l, const int_int_pair& r) // 첫번째 값을 기준으로 내림차순 비교하는 comparator

{

return l.first > r.first;

}

 

 

 

int main()

{

vector<int_int_pair> A; // vector setting

 

srand( unsigned(time (NULL)));

 

for (int i=0; i<N_SIZE ; i++)

{

A.push_back(int_int_pair(i,i)); // (value, index) setting

}

 

random_shuffle(A.begin(), A.end()); // 마구 마구 섞기

 

 

cout << "정렬전\nValue\tIndex\n" ;

 

for (int i=0; i<N_SIZE ; i++) // 섞인거 확인하기

{

cout << A[i].first << "\t" << A[i].second << endl;

}

 

cout << "\n\n" ;

 

 

stable_sort(A.begin(),A.end(), comparator); // 정렬 하기

 

cout << "정렬후\nValue\tIndex\n" ;

for (int i=0; i<N_SIZE ; i++) // 정렬됐나 확인하기

{

cout << A[i].first << "\t" << A[i].second << endl;

}

 

return 0;

}

 

위 코드에 따라 다음과 같이 내림 차순 정렬 되게 됩니다.





  1. 종이눈 2018.04.25 12:40

    감사합니다^^ 인덱스 정렬에 내림차순까지 제가 필요했던게 전부 들어있네요

    • 남성 2018.04.25 19:12 신고

      도움되었다니 다행이네요. 방문해 주셔서 감사합니다. ^^

MATLAB 은 공학적으로 굉장히 편리 한 툴입니다. 하지만 편리함 속에는 단점도 있는 게 사실 입니다. 쉽다고 함부로 쓰다가는 정말 예상치 못한 결과에 당황하는 경우가 있곤 합니다. 따라서 MATLAB 함수 등을 쓰실 때는 help 문 이나 예제 등을 통해 정확히 알고 난 이후에 이용하는 것이 좋습니다.

 

이번 포스팅에서는 그럼 기본 함수 몇 가지를 비롯한 몇몇 주의 할 점 들에 대해 설명 드리겠습니다.

 

첫 번째로 소개해 드릴 함 수는 sort() 함수 입니다. 함수 이름만 봐도 이게 정렬을 해주는 함수구나 하는 건 아실 겁니다.

예를 통해 설명해 보도록 하죠~

 

A=magic(3)

A =

8 1 6

3 5 7

4 9 2

 

A 에 대해 sort() 함수를 적용해 보면 다음과 같습니다.

 

A1=sort(A)

A1 =

3 1 2

4 5 6

8 9 7

 

각 열에 대해 오름차순으로 정렬이 되는 것을 보실 수 있습니다.

 

각 행 마다 정렬을 하기 위해서는 아래와 같이 dimension 값을 2로 설정 해 주면 됩니다.

 

A2=sort(A,2)

A2 =

1 6 8

3 5 7

2 4 9

 

 

그럼 내림차순으로 정렬을 한번 해 보죠. 내림차순을 하려면 'descend' 라는 인자를 하나 추가해 주면 됩니다. 다음과 같이 처리 해 보죠 각 열 별로 내림차순으로 정렬되는 것을 알 수 있습니다. 오름차순이 default 값 이지만 'ascend' 를 써 주기도 합니다.

 

A3=sort(A,'descend')

A3 =

8 9 7

4 5 6

3 1 2

 

다음으로 max() 함수에 대해 설명 드리겠습니다. max() 함수는 큰 값을 찾아 주는 함수 입니다.

 

max_A=max(A)

max_A =

8 9 7

 

두 매트릭스의 각 인자 중 큰 값을 찾아 낼 수도 있습니다. 다음과 같이 매트릭스 B 를 만들어 보죠

 

B=ones(3)*5

B =

5 5 5

5 5 5

5 5 5

 

다음 결과에서는 matrix A, B 의 각 인자에 대해 비교를 해서 큰 값을 뽑아 낸 것을 알 수가 있습니다. 이렇게 이용할 때는 당연히 A, B 의 크기가 같아야 합니다.

 

max_AB=max(A,B)

max_AB =

8 5 6

5 5 7

5 9 5

 

 

그럼 각 행 별로 가장 큰 값을 찾을 때는 다음 코드와 같이 중간에 [] 를 써주고 세 번째 인자에 dimension을 써줘야 합니다. 이 부분이 max() 함수를 사용하면서 많이 실수 하는 부분입니다.

 

max_A_r=max(A,[],2)

max_A_r =

8

7

9

 

max() 함수는 최대 값과 그 인덱스도 알려 줍니다. 다음과 같이 써주면 됩니다.

 

[max_A, max_I] = max(A)

max_A =

8 9 7

max_I =

1 3 2

 

위 결과를 보면 첫 번째 열에서는 8 이 가장 크고 1 열에서의 인덱스는 1 이라는 것을 알 수 있습니다. 두 번째 열에서는 9 가 가장 크고 2열에서의 인덱스는 3, 세 번째 열에서는 7이 가장 크고 3열에서의 인덱스는 2 라는걸 알 수가 있죠.

 

이상으로 max() 함수의 설명을 마치겠습니다. min() 함수는 최소값을 구하는 함수이며 그 사용법은 max() 함수와 완전 동일 합니다.

 

다음으로 if ~ end 사용시의 주의 사항에 대해 말씀 드리겠습니다. if 문은 다음과 같이 조건이 만족하면 그 안의 내용을 실행하게 됩니다. m 파일 작성시 기본적으로 ;(세미콜론)을 붙여 주곤 하지만 <if 조건 > 라인의 뒤에는 세미콜론을 안 붙여도 됩니다. 간혹 다 붙이시는 분들이 있어서 말씀 드리는 겁니다.

 

if 조건

statement ;

end

 

이때 조건에 대한 판단이 굉장히 중요 합니다. if 문은 조건이 벡터 인 경우 그 결과가 다 참이어야만 if 안의 내용을 실행 합니다.

 

다음과 같은 예를 보죠

 

A=0

if [1 1 1]

A=100;

end

 

A =

100

 

위 예에서는 [1 1 1] 이므로 모두 참 입니다. 따라서 A=100 이 실행이 됩니다.

 

하지만 아래 코드에서는 0 이 거짓이므로 A=200 이 실행이 안 되는 거죠. 이 부분을 간과하고 코딩 시에는 정말 이해 못할 결과들이 많이 나오니 주의 하시길 바랍니다.

 

A=0

if [0 1 1]

A=200;

end

A =

0

 

 

마지막으로 for ~ end 문에 대해 설명 드리겠습니다. 기본적으로는 다음과 같이 씁니다. <for n=1:5 > 뒤에는 세미콜론을 안 붙여도 됩니다.

 

for n=1:5

disp(n)

end

 

1

2

3

4

5

 

 

이렇게 쓸 수도 있습니다.

 

n=1:5

n =

1 2 3 4 5

 

 

for k=n

disp(k)

end

 

1

2

3

4

5

 

for 문에서 등호의 오른쪽이 벡터일 경우에는 루프 마다 그 값들을 차례로 k 라는 변수에 넣고 실행이 되게 됩니다.

 


  1. 이진성 2014.03.28 18:38

    잘 봤습니다~! 특히 if [1 1 1]이 새롭군요~! 혹시 하나만 참이어도 실행되는 함수는 없죠?

    • 남성 2014.03.28 23:49 신고

      방문해 주셔서 감사합니다. ^^ 하나만 참이어도 실행되게 하고 싶다면 any() 함수를 사용하시면 됩니다 if any([0 1 1]) 과 같이 말이죠~

  2. 김지수 2016.05.15 11:50

    안녕하세요! 많은 도움을 받고갑니다. 질문하나 해도 될까요? 1x16 행렬에서 map = [0 1 3 2 6 7 5 4 12 13 15 14 10 11 9 8] 이런 값이 있는데 [x y] = sort(map)을 실행하게 되면
    x 값은 오름차순의 값으로 가는걸 이해 했으나 y값은 [1 2 4 3 8 7 5 6 16 15 13 14 9 10 12 11]로 나오는데 이해가 되지않습니다. 왜그런건가요??

+ Recent posts