[swift] 정규식을 활용하여 process 항목 추출하기
블로그를 자주 안하니 참 일기장 들여다보는기분.......
정규식이 항상 어려워서 피하다가 결국에 이번에 끝장을 보려고 공부해서 정리하겠다...
정규식
정규표현식 또는 정규식이라고 불리며 문자열에서 특정한 규칙을 가진 문자열의 집합을 표현하는 식이다.
특정 문자열에 원하는 규칙을 세운 정규식을 적용하면 원하는 문자열을 도출한다거나, 해당 문자열 안에 원하는 문자가 있는지 판별할 수 있다.
식이라고 생각하면된다. 처음엔 정규식 자체가 너무 외계어 같아 외면해왔으나....자주자주 마주하다보면 좀 친해지는 느낌을 받을 수 있을것이다.
그동안 정규식을 쓰기 싫어 spilit, contains같은 스위프트 문자열 함수만 즐겨 사용했으나 이번엔 해당 함수로만 처리할 수 없는 부분들이 많아 정규식을 사용하였다.
나도 아직 친해지는 중이니... 좀더 알아보도록 하자
일단 오늘 처리할 문자열은
ahnlab@Ahnlabui-MacBookAir-2 ~ % ps auxc -o ppid
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND PPID
ahnlab 484 6.6 1.6 409759680 275024 ?? S 화09AM 83:01.54 syncdefaultsd 1
_windowserver 140 6.5 1.0 410307552 161760 ?? Ss 화09AM 260:29.28 WindowServer 1
ahnlab 685 1.4 0.5 409231104 84080 ?? S 화09AM 40:45.72 NuoRDS Agent 665
root 342 1.2 0.0 409153024 6720 ?? Ss 화09AM 43:41.96 sysmond 1
_mdnsresponder 156 1.1 0.0 408511904 7584 ?? Ss 화09AM 15:01.88 mDNSResponder 1
_driverkit 275 1.1 0.0 408555584 7696 ?? Ss 화09AM 19:53.44 com.apple.Driver 1
ahnlab 490 1.0 4.1 412638352 691456 ?? S 화09AM 32:12.82 Xcode 1
root 33439 0.9 0.1 409428288 19088 ?? Ss 6:29PM 0:00.42 CFNetworkAgent 1
ahnlab 2748 0.5 1.6 411617376 274944 ?? S 화11AM 17:23.43 Microsoft Outloo 1
_networkd 214 0.4 0.1 408636352 12480 ?? Ss 화09AM 7:07.06 symptomsd 1
root 79 0.4 0.1 408796048 10080 ?? Ss 화09AM 5:06.98 configd 1
root 87 0.3 0.2 408873120 30800 ?? Ss 화09AM 6:31.29 logd 1
ahnlab 516 0.3 1.0 410083952 176000 ?? S 화09AM 1:17.03 Terminal 1
root 1 0.1 0.1 408636240 22208 ?? Ss 화09AM 8:46.10 launchd 0
ahnlab 652 0.1 12.9 14720924 2164032 ?? S 화09AM 19:36.40 Microsoft Teams 479
root 97 0.1 0.4 409294144 65312 ?? Ss 화09AM 2:23.16 mds 1
ahnlab 28559 0.1 4.7 14533548 784208 ?? S 1:33PM 1:03.37 HRS_AhnLab Helpe 28555
ahnlab 33393 0.1 0.1 408605392 23904 ?? S 6:25PM 0:00.14 mdworker_shared 1
ahnlab 33351 0.1 0.1 408668144 13600 ?? S 6:23PM 0:01.83 debugserver 7478
위와같은 터미널에서 ps명령어를 쳤을때 나오는 프로세스 정보이다.
각 줄의 문장에서 user, pid, cpu, mem등 항목별로 얻을것이고, 그에 따른 규칙을 찾아 정규식을 적용한다.
정규식을 세우면서 자주 나오는 문법들을 먼저 짚고 넘어가겠다.
1. ^
문자열의 시작이다.
^ 하나만 쓰는것이 아닌 문자열 규칙이 붙는데, 해당 규칙으로 시작하는 문자열을 판별하겠다는 의미이다.
예를들어 ^숫자로만 이루어진 규칙 이 하나의 식이면, 문자열이 숫자로만 이루어진 문자로 시작하는 문자에 한해서 판별, 도출한다.
"안녕하세요 제이름은 나무발발이이고요, 나이는 883725573 8 002 1 0 0 0 입니다. 집은 제주도에 있어요 "
가 하나의 문자열이라고 해보자. 여기서 위에 언급한 규칙을 적용한다면, 도출되는 문자열은 없다.
반대로 ^문자로만 이루어진 규칙 을 적용하게 된다면, 도출되는 문자열은 "안녕하세요" 가 될것이다.
2. []
대괄호안에 문자열 규칙을 넣는것으로, 대괄호하나가 문자의 단위가 된다. 규칙은 0~9 사이의 문자인지 , 소문자로 이루어진 문자인지, 대문자로 이루어진문자인지 또는 특수문자인지에 대한 여부를 넣으면된다.
표기는 숫자는 0-9 (0에서 9 사이의 문자) 소문자는 a-z (a~z사이의 문자) 대문자는 A-Z 이런식으로 표기하면 된다.
예시로 숫자로만 이루어진 문자를 찾는다고 하자, 규칙은 [0-9]가 될 것이다. 또는 숫자, 소문자로 이루어진 문자열과 같이 여러규칙이 있어야 한다면 [0-9a-z] 로 이어서 표기한다.
위에 예시로 나온 문자열에 적용한다면,
8,8,3,7,2,5,5,7,3,8,0,0,2,1,0,0,0 로 나올것이다. 883725573, 8, 002, 1, 0, 0, 0 을 예상했을텐데 말이다. 이는 문자열에 길이 규칙을 지정해주지 않아서이다.
또한 대괄호 안에도 ^를 넣을 수 있는데, 이때 대괄호안의 ^는 부정의(not) 의미를 갖게된다.
예를 들어 [^0-9]는 0-9로 이루어지지 않은 문자열을 의미하게 된다.
3. {,}
길이를 지정해주는 규칙이다. 콤마 기준으로 왼쪽은 최소길이, 오른쪽은 최대길이를 지정한다.
오른쪽은 지정해주지 않아도 된다. 다만 최대길이를 지정하지 않으면 최대길에 제한이 없다는 뜻이 된다.
예를 들어 {2,8} 은 2~8길이의 문자열이 되고, {1,} 는 최소 1길이 이상의 문자열을 의미한다
그럼 2번 예시에서 883725573, 8, 002, 1, 0, 0, 0 과 같이 도출하려면 어떻게 해야할까?
구하려는 문자열 길이가 전부 1이상이니 {1,}을 해주어도 되고, 최대 길이가 9이니 {1,9} 로 표기해주어도 같은 결과가 나온다.
4. +
특정한 규칙을 지키는 형태로 문자열이 이루어져있다면, +를 사용해 문자열의 형식을 지정할 수 있다.
[규칙]+[규칙]+[규칙] 과 같은 형식으로 특정한 문자열의 형태를 지정할 수 있다. 이는 이메일의 정규식에서도 많이 활용되는데, 이메일은 @가 필수적으로 들어가야 하므로
[규칙]+@[규칙]+\\.[규칙] 과 같이 나타낼 수 있다.
이제 맨 위에서 언급한 프로세스를 각 항목마다 출력해보자. 해당 항목을 오류없이 도출하려면 규칙을 잘 알아야하고 그에 맞는 정규식을 세워야 한다. 내가 세운 정규식은 다음과 같다.
- user : 소문자로 이루어져있고, _ 기호가 포함될 수 있다. 길이는 1이상
- PID , VSZ , RSS , PPID : 숫자로만 이루어져있음. 길이는 1이상
- CPU ,MEM : 소수점 ( . )이 포함되어있고, 점 앞뒤로 숫자로 이루어져있다. 길이는 1 이상
- TT : ??또는 소문자,숫자로 이루어져있는 문자열이다.
- STARTED : 화 9:30PM 또는 11:39AM 와 같이 두가지 형태로 존재하며, 한글+공백+숫자+:+숫자+대문자영어 또는 숫자+:+숫자+대문자영어와 같은 형태로 이루어져있다.
- TIME : 숫자 + : + 숫자 + . + 숫자 형태
- COMMAND : 대소문자, 공백 , _ 기호로 이루어져있다.
위에 따른 세운 규칙은 다음과 같다.
static let text = "[a-zA-Z_?]{1,}" //USER또는 STAT 형식
static let command = "[a-zA-Z_ ]{1,}" //COMMAND
static let number = "[^A-Za-z ?_]{1,}" //숫자로만 이루어진 항목들
static let krDate = "[ㄱ-ㅎ|ㅏ-ㅣ|가-힣]+[ ]+[0-9]+[A-Z]{1,}" //화 9:30AM 과 같은 형식
static let date = "[0-9]+[:]+[0-9]+[A-Z]{1,}" // 11:09AM과 같은 형식
static let time = "[0-9]+[:]+[0-9]+[.]+[0-9]{1,}" // 11:22.22 과 같은 형식
정규식은 차차 추가할거니 빠진 부분에 대해선 이후에 수정하겠다.