[Linux] 콘솔 출력에 색상값 넣기

리눅스는 쓰면 쓸수록 최선이자 최고이다. 더욱이 Windows 운영체제에서도 WSL로 리눅스를 활용할 수 있으니 리눅스의 가치상승은 더 높아졌다. 그와함께 Windows의 가치도 Up!

본론으로 돌아와서.. 리눅스에서 서버를 기동하고 그 사용 로그를 화면에 출력한다. 여기에 중요한 내용에 색상값을 넣어 시각적으로 보다 더 쉽게 내용을 파악하고자 한다. 즉, 최종 결과물은 다음과 같다.

보면 SUCCESSED와 FAILED에 대해 각각 초록색과 빨간색으로 표시하고 그외는 하얀색으로 표시하고 있다. 이를 위해서 리눅스의 sed 명령어가 활용되는데, 이를 위한 쉘은 다음과 같다.

# color
szColBk="";	szColBk1=""	# black
szColRe="";	szColRe1=""	# red
szColGr="";	szColGr1=""	# green
szColYe="";	szColYe1=""	# yellow
szColBl="";	szColBl1=""	# blue
szColPu="";	szColPu1=""	# magenta(purple)
szColCy="";	szColCy1=""	# cyan
szColGy="";	szColWh=""	# white
szNormal=""

# command
sed \
    -e "s/\(SUCCESSED\)/${szColGr1}\\1$szNormal/g" \
    -e "s/\(FAILED\)/${szColRe1}\\1$szNormal/g" \

위의 코드를 coloring.sh라는 파일로 저장하고 실행할 수 있도록 권한을 부여해 두고.. 로그 출력을 위해 다음 명령을 수행하면 된다.

 tail /web_home/2020-06-13.log -f | ./coloring.sh

[Java] 두 문자열간의 유사도 구하기

두개의 문자열이 있을때, 얼마나 유사한지를 백분율의 개념인 0~1사이의 값으로 확인할 수 있을까? 즉 똑같은 문자열이라면 1을 전혀 다른 문자열이라면 0이라는 값으로 말이다. 구글링해보니 edit distance 계산을 통해 얻을 수 있단다. 가장 일반적은 구현체는 Levenshtein의 Distance Algorithm이라고 하고, 그 구현 함수는 다음과 같다. (출처: http://rosettacode.org/wiki/Levenshtein_distance#Java)

private double similarity(String s1, String s2) {
    String longer = s1, shorter = s2;
	
    if (s1.length() < s2.length()) {
        longer = s2; 
        shorter = s1;
    }
	
    int longerLength = longer.length();
    if (longerLength == 0) return 1.0;

    return (longerLength - editDistance(longer, shorter)) / (double) longerLength;
}

private int editDistance(String s1, String s2) {
	s1 = s1.toLowerCase();
    s2 = s2.toLowerCase();
    int[] costs = new int[s2.length() + 1];
    
    for (int i = 0; i <= s1.length(); i++) {
        int lastValue = i;
        for (int j = 0; j <= s2.length(); j++) {
            if (i == 0) {
            	costs[j] = j;
            } else {
                if (j > 0) {
                    int newValue = costs[j - 1];
                    
                    if (s1.charAt(i - 1) != s2.charAt(j - 1)) {
                    	newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
                    }
                    
                    costs[j - 1] = lastValue;
                    lastValue = newValue;
                }
            }
        }
        
        if (i > 0) costs[s2.length()] = lastValue;
    }
    
    return costs[s2.length()];
}

사용은 similarity 함수에 비교할 문자열 2개를 지정하면 비슷한 정도가 0~1 사이의 값으로 반환된다.

CAD 색상 테이블 (Color Table)

지리정보시스템(GIS)의 원시 데이터 중 CAD에 대한 시각화를 위한 색상 테이블을 정리한 표입니다.

0 (#000000)
1 (#FF0000)
2 (#FFFF00)
3 (#00FF00)
4 (#00FFFF)
5 (#0000FF)
6 (#FF00FF)
7 (#FFFFFF)
8 (#414141)
9 (#808080)
10 (#FF0000)
11 (#FFAAAA)
12 (#BD0000)
13 (#BD7E7E)
14 (#810000)
15 (#815656)
16 (#680000)
17 (#684545)
18 (#4F0000)
19 (#4F3535)
20 (#FF3F00)
21 (#FFBFAA)
22 (#BD2E00)
23 (#BD8D7E)
24 (#811F00)
25 (#816056)
26 (#681900)
27 (#684E45)
28 (#4F1300)
29 (#4F3B35)
30 (#FF7F00)
31 (#FFD4AA)
32 (#BD5E00)
33 (#BD9D7E)
34 (#814000)
35 (#816B56)
36 (#683400)
37 (#685645)
38 (#4F2700)
39 (#4F4235)
40 (#FFBF00)
41 (#FFEAAA)
42 (#BD8D00)
43 (#BDAD7E)
44 (#816000)
45 (#817656)
46 (#684E00)
47 (#685F45)
48 (#4F3B00)
49 (#4F4935)
50 (#FFFF00)
51 (#FFFFAA)
52 (#BDBD00)
53 (#BDBD7E)
54 (#818100)
55 (#818156)
56 (#686800)
57 (#686845)
58 (#4F4F00)
59 (#4F4F35)
60 (#BFFF00)
61 (#EAFFAA)
62 (#8DBD00)
63 (#ADBD7E)
64 (#608100)
65 (#768156)
66 (#4E6800)
67 (#5F6845)
68 (#3B4F00)
69 (#494F35)
70 (#7FFF00)
71 (#D4FFAA)
72 (#5EBD00)
73 (#9DBD7E)
74 (#408100)
75 (#6B8156)
76 (#346800)
77 (#566845)
78 (#274F00)
79 (#424F35)
80 (#3FFF00)
81 (#BFFFAA)
82 (#2EBD00)
83 (#8DBD7E)
84 (#1F8100)
85 (#608156)
86 (#196800)
87 (#4E6845)
88 (#134F00)
89 (#3B4F35)
90 (#00FF00)
91 (#AAFFAA)
92 (#00BD00)
93 (#7EBD7E)
94 (#008100)
95 (#568156)
96 (#006800)
97 (#456845)
98 (#004F00)
99 (#354F35)
100 (#00FF3F)
101 (#AAFFBF)
102 (#00BD2E)
103 (#7EBD8D)
104 (#00811F)
105 (#568160)
106 (#006819)
107 (#45684E)
108 (#004F13)
109 (#354F3B)
110 (#00FF7F)
111 (#AAFFD4)
112 (#00BD5E)
113 (#7EBD9D)
114 (#008140)
115 (#56816B)
116 (#006834)
117 (#456856)
118 (#004F27)
119 (#354F42)
120 (#00FFBF)
121 (#AAFFEA)
122 (#00BD8D)
123 (#7EBDAD)
124 (#008160)
125 (#568176)
126 (#00684E)
127 (#45685F)
128 (#004F3B)
129 (#354F49)
130 (#00FFFF)
131 (#AAFFFF)
132 (#00BDBD)
133 (#7EBDBD)
134 (#008181)
135 (#568181)
136 (#006868)
137 (#456868)
138 (#004F4F)
139 (#354F4F)
140 (#00BFFF)
141 (#AAEAFF)
142 (#008DBD)
143 (#7EADBD)
144 (#006081)
145 (#567681)
146 (#004E68)
147 (#455F68)
148 (#003B4F)
149 (#35494F)
150 (#007FFF)
151 (#AAD4FF)
152 (#005EBD)
153 (#7E9DBD)
154 (#004081)
155 (#566B81)
156 (#003468)
157 (#455668)
158 (#00274F)
159 (#35424F)
160 (#003FFF)
161 (#AABFFF)
162 (#002EBD)
163 (#7E8DBD)
164 (#001F81)
165 (#566081)
166 (#001968)
167 (#454E68)
168 (#00134F)
169 (#353B4F)
170 (#0000FF)
171 (#AAAAFF)
172 (#0000BD)
173 (#7E7EBD)
174 (#000081)
175 (#565681)
176 (#000068)
177 (#454568)
178 (#00004F)
179 (#35354F)
180 (#3F00FF)
181 (#BFAAFF)
182 (#2E00BD)
183 (#8D7EBD)
184 (#1F0081)
185 (#605681)
186 (#190068)
187 (#4E4568)
188 (#13004F)
189 (#3B354F)
190 (#7F00FF)
191 (#D4AAFF)
192 (#5E00BD)
193 (#9D7EBD)
194 (#400081)
195 (#6B5681)
196 (#340068)
197 (#564568)
198 (#27004F)
199 (#42354F)
200 (#BF00FF)
201 (#EAAAFF)
202 (#8D00BD)
203 (#AD7EBD)
204 (#600081)
205 (#765681)
206 (#4E0068)
207 (#5F4568)
208 (#3B004F)
209 (#49354F)
210 (#FF00FF)
211 (#FFAAFF)
212 (#BD00BD)
213 (#BD7EBD)
214 (#810081)
215 (#815681)
216 (#680068)
217 (#684568)
218 (#4F004F)
219 (#4F354F)
220 (#FF00BF)
221 (#FFAAEA)
222 (#BD008D)
223 (#BD7EAD)
224 (#810060)
225 (#815676)
226 (#68004E)
227 (#68455F)
228 (#4F003B)
229 (#4F3549)
230 (#FF007F)
231 (#FFAAD4)
232 (#BD005E)
233 (#BD7E9D)
234 (#810040)
235 (#81566B)
236 (#680034)
237 (#684556)
238 (#4F0027)
239 (#4F3542)
240 (#FF003F)
241 (#FFAABF)
242 (#BD002E)
243 (#BD7E8D)
244 (#81001F)
245 (#815660)
246 (#680019)
247 (#68454E)
248 (#4F0013)
249 (#4F353B)
250 (#333333)
251 (#505050)
252 (#696969)
253 (#828282)
254 (#BEBEBE)
255 (#FFFFFF)

Java로 텍스트 파일 읽기

버퍼 방식으로 사용하여 빠르게 텍스트 파일을 읽는 예제 코드입니다. 제가 Java 아재라서, 새로운 Java의 더욱 효과적인 파일 읽기 API가 분명 있을것 같은데.. 혹 있다면 추천 부탁드리겠습니다.

package tst;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;

public class MainEntry {
	public static void main(String[] args) {
		String filePath = "D:\\__Data__\\DXF\\1_5000\\NGII_DTM_5000_울산_남구_35905\\35905090.dxf";

		FileInputStream fs = null;
		InputStreamReader isr = null;
		BufferedReader br = null;
		
		try {
			long startTime = System.currentTimeMillis();
			
			fs = new FileInputStream(filePath);
			isr = new InputStreamReader(fs, "euc-kr");
			br = new BufferedReader(isr);
			
			String line = null;
			while((line = br.readLine()) != null) {
				//System.out.println(line);
			}
			
			long finishTime = System.currentTimeMillis();
			System.out.println("소요시간: " + (finishTime - startTime) + " ms");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(br != null) br.close();
				if(isr != null) isr.close();
				if(fs != null) fs.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
}

위의 코드로 7.52MB 크기의 파일을 모두 읽는데, 약 0.13초정도 소요됩니다. 사용하고 있는 개발 환경은 i7-6700HQ@2.60GHz의 RAM 16GB 노트북입니다.

vi 편집기 명령 정리

이 글은 콘솔 환경에서 텍스트를 편집할 수 있는 vi 편집기 사용을 위해 요약한 글로 vi를 처음 접하는 분들은 다른 글을 참조하시기 바랍니다.

vi는 총 4가지 상태를 가지며 다음과 같은 상태 전환이 이루어집니다.

EX 모드

  • 변경된 내용 저장 w
  • 변경된 내용 저장하고 종료 wq
  • 변경된 내용 무시하고 종료 q!
  • 종료 q
  • 문자열 검색(예: boy) /boy
    • 다음 검색 문자열 n
    • 이전 검색 문자열 N
  • 문자열 변경(예: boy를 guy로 변경) %s/boy/guy/ig
  • 줄 번호 표시 set nu
  • 줄 번호 감추기 set nonu

명령 모드

  • 현재 커서 위치에서 편집 모드로 전환 i
  • 현재 커서 위치 줄의 첫문자 위치에서 편집 모드로 전환 I
  • 현재 커서의 바로 뒤에서 편집 모드로 전환 a
  • 현재 커서 위치 줄의 마지막 위치에서 편집 모드로 전환 A
  • 왼쪽으로 커서 위치 이동 h, ←
  • 오른쪽으로 커서 위치 이동 l, →
  • 위쪽으로 커서 위치 이동 k, ↑
  • 아래쪽으로 커서 위치 이동 j, ↓
  • 다음 단어 단위로 커서 이동 w
  • 이전 단어 단위로 커서 이동 b
  • 커서 위치 라인의 첫 문자로 이동 ^, 0
  • 커서 위치 라인의 끝 문자로 이동 $
  • 마지막 라인으로 이동 G
  • 100번째(1부터 시작) 라인으로 이동 100G
  • 편집된 내용 되돌리기 u
  • 커서 위치 한글자 삭제 x
  • 커서 위치를 포함해 세 글자 삭제 3x
  • 커서 앞의 글자 삭제 X
  • 커서 위치의 단어 단위로 삭제 dw
  • 커서 위치 줄 삭제 dd
  • 커서 위치의 줄을 포함해 세 줄 삭제 3dd
  • 커서 앞의 글자 삭제 X
  • 커서 위치에서 줄 끝 문자까지 삭제 D
  • 커서 위치의 줄을 버퍼에 복사 yy
  • 커서 위치의 줄을 포함해 세 줄을 버퍼에 복사 3yy
  • 버퍼에 복사된 문자열을 커서 위치에 붙여넣기 p
  • 버퍼에 복사된 문자열을 커서의 앞 위치에 붙여넣기 P
  • 한 글자만 수정 r
  • 커서 다음 위치에 빈줄 추가 o
  • 커서 이전 위치에 빈줄 추가 O
  • 커서 위치의 라인과 다음 라인을 한 라인으로 붙임 J

비주얼 모드

  • 글자 단위로 선택(명령모드에서 전환시) v
  • 라인 단위로 선택(명령모드에서 전환시) V
  • 블럭 단위로 선택(명령모드에서 전환시) ^v
  • 선택된 텍스트를 버퍼에 복사 y
  • 선택된 텍스트를 삭제 d, x