네이버 검색에서 로또 당첨번호 파싱하기 – Swift + CommandLine

네이버 검색으로부터 로또 당첨 번호를 파싱하는 방법에 대해서 살펴보자. 기본적으로 이 작업을 수행하기 위해서는 두 가지 기술을 사용할 것이다.

  1. NSURLSession :  웹페이지 데이터를 받아와야 하기 때문에 네트워킹 API 를 사용해야 한다.
  2. NSRegularExpression : 받아온 데이터는 HTML 페이지의 소스 데이터이며, 여기서 로또 당첨번호의 내용을 추출하기 위해 간단한 정규식을 사용할 것이다.

아, 그리고 참고로 여기서 사용된 Swift 버전은 4.0이다.

준비 과정

네이버는 로또 당첨번호 검색에 대해서 일반적인 웹문서 결과가 아닌 별도로 디자인된 영역으로 당첨번호를 예쁘게 표시해주고 있다. 실제로 네이버에서 “로또 당첨번호”라는 키워드로 검색해보면 다음과 같은 화면을 볼 수 있다.

여기서 로또 회차 부분을 클릭하면 다른 회차의 당첨번호도 알 수 있는데, 다른 회차들을 선택해보자. 이 때, 브라우저의 주소창을 보면 일정한 패턴으로 구성되는 것을 알 수 있다.

https://search.naver.com/search.naver?sm=tab_drt&where=nexearch&query=792회로또

즉 위의 주소에서 회차에 해당하는 번호값만 바뀌는 것을 알 수 있다. 그러면 당첨 번호는 어떻게 알 수 있을까? 색색의 예쁜 숫자 공을 선택해서 브라우저의 인스펙터에서 조사해보면 “ball번호“의 패턴으로 클래스가 적용되어 있는 것을 확인할 수 있다.

따라서 ball(\d+) 라는 정규식 패턴으로 당첨번호에서 숫자부분만 손쉽게 추출할 수 있다.

정규식으로 당첨번호를 추출하여 출력하기

URLSession을 사용해서 간단한 데이터 받아오기라는 글에서 URLSession을 사용하는 간단한 방법을 소개한 적이 있는데, (Data) -> Void 타입의 완료 핸들러를 이용해서 웹주소로부터 HTTP 통신을 통해 받아온 데이터를 처리할 수 있다고 하였다. 그렇다면 이 부분을 먼저 작성해보자. 네이버는 웹페이지에 UTF8 인코딩을 사용하고 있으므로 받아온 데이터를 UTF8로 디코딩하여 문자열을 얻고, 여기에서 위 패턴을 적용하여 번호들을 추출할 수 있다.

func parseBallNumbers(_ data: Data) {
  guard let html = String(data:data, encoding:.utf8) else { return }
  let regex = try! NSRegularExpression(pattern: "ball(\\d+)", options:[])
  else { return }

  let matches = regex.matches(in: html, options:[], range: NSMakeRange(0, html.count))
  let results = matches.map{ (html as NSString).substring(with: $0.range(at:1)) }
  // 6개의 당첨번호와 1개의 보너스번호
  let nums = results[..<6].joined(separator: ", ")
  let bonus = results.last!
  print("\(nums) - 보너스: \(bonus)")
}

데이터를 요청하기

데이터를 받아와서 당첨번호를 추출하고 출력하는 함수를 작성했으니, 이제 데이터를 받아올 함수를 작성할 차례이다. 단, 나는 여기서 명령줄에서 실행되는 버전을 상정하고 있는데 URLSession의 모든 동작은 철저하게 비동기로 동작한다. 따라서 데이터 작업 객체의 resume()은 비동기로 네트워크 통신을 개시하면서 즉시 리턴하기 때문에 응답을 기다릴 필요가 있다. 이 경우, 메인 스레드에서 런루프를 실행하여 네트워크 통신을 기다리고, 완료 핸들러 내에서 런루프를 중지하고 끝내는 방식으로 처리한다.

func processURL(_ url: URL, handler: @escaping (Data) -> Void) {
  let task = URLSession.shared.dataTask(with: url){ data, _, _ in
    defer { CFRunLoopStop(CFRunLoopGetMain()) }
    guard let data = data else { return }
    handler(data)
  }
  task.resume()
  CFRunLoopRun()
}

조립하기

이제 우리는 네트워크 통신으로 웹 페이지를 받아오고, 데이터를 파싱하는 함수를 모두 갖게 되었다. 이를 조립하여 원하는 동작을 이루어보자.

func main() {
  if let s = readLine(), let i = Int(s) {
    let address = "https://search.naver.com/search.naver?sm=tab_drt&where=nexearch&query=\(i)회로또"
    let encodedAddress = address.appendingPercentEncoding(withAllowedCharacters:.urlQueryAllowed)!
    let url = URL(string:encodedAddress)!
    processURL(url, handler: parseBallNumbers)
}

(Dos) 명령줄에서 For 사용하기

나는 vim을 소스에서 mingw-w64로 컴파일하여 사용중이다. vim을 컴파일한 결과물은 소스 디렉토리에 생성된다. 이 파일을 원래 vim 이 있던 자리로 복사하는 과정은 꽤나 귀찮을 수 있다. 물론 원래 vim.exe 파일이 있던 자리에만 복사하면 되지 그게 무슨 문제냐…고 할 수 있지만 Git 디렉토리 내에도 vim 이 있고 msys 내에도 vim 이 있기 때문에 좀 곤란하다. 한방에 할 수 있는 방법이 없을까?

물론 수동으로 해당 위치들을 파이썬 스크립트 같은 곳에 지정해놓고 복사하는 코드를 짜는 것도 방법이겠다.

from pathlib import Path
import subprocess
from shutil import copyfile

def main():
    paths = [Path(x).parent for x in subprocess.check_output(['where', 'vim'], 
        universal_newlines=True).split('\n')][1:]

    exes = ('vim.exe', 'gvim.exe')
    for e in exes:
        if (Path(__file__).parent / e).exists():
            print("FILE {} IS CHECKED, START COPYING".format(e))
            for p in paths:
                if p == Path(__file__).parent:
                    continue
                try:
                    print("  COPYING {} TO {}".format(e, str(p)))
                    copyfile(str(e), str(p / e))
                except:
                    print("    ERROR DURING COPYING {} TO {}".format(e, str(p)))

if __name__ == '__main__':
    main()

근데 이건 너무 귀찮으니까 (아니, 이 시점에 이미 다 짜두었는데?) 다음과 같이 도스의 FOR 명령을 쓸 수 있다. 사실 DOS 역시 FOR 문을 지원하고 있는데, 보통 쉘에서 반복문은 한 번 알아두면 요긴하게 쓸 데가 많긴하다.

FOR /F "skip=1 delims=" %G IN ('where vim') DO COPY /Y vim.exe"%~dpG"

몇 가지 설명을 곁들여 보자. 자세한 내용은 명령 프롬프트 상에서 HELP FOR를 입력해서 볼 수 있다.

  1. /F 옵션은 파일(집합) 및 문자열이나 명령의 결과의 각 행에 대해서 특정 명령을 반복합니다.
  2. /F 뒤에는 옵션이 옵니다. 각 옵션은 따옴표 안에 들어가며 공백으로 구분합니다.
  3. skip=1은 첫번째 행을 무시한다는 의미입니다. (왜냐면 첫번째 행은 현재 디렉토리가 될거기 때문에 파일을 자기 자신으로 복사할 수 없습니다.)
  4. delims=는 각 행의 기본 구분값(공백이나 탭)을 무시한다는 의미입니다. 엄청 귀찮게도 "Program Files (x86)"과 같이 공백이 들어간 디렉토리명을 시스템이 강제하는 병신같은 윈도우….
  5. %G는 각 행을 받을 변수입니다. 만약 이 명령이 배치파일 내에서 사용된다면 %%G이라고 두번 써야 합니다.
  6. IN 다음에는 집합이 옵니다. 여기서는 ('where vim')이라고 %PATH%에 포함된 vim 실행파일 경로를 찾습니다.
  7. DO 다음에는 실행할 명령입니다.
  8. %~dpG%G를 확장합니다. 드라이브이름과 경로로 확장한다는 의미입니다. 이 때 디렉토리 안에 공백이 들어간 병신같은 시스템이므로 이를 따옴표로 둘러싸야 한 덩어리의 경로로 인식됨에 주의합니다.

따라서 최종적으로 생성한 deplay.bat 의 내용은 다음과 같다.

@echo off
FOR /F "skip=1 delims=" %%G IN ('where vim') DO COPY /Y vim.exe "%%~dpG"
FOR /F "skip=1 delims=" %%G IN ('where vim') DO COPY /Y gvim.exe "%%~dpG"
echo on

파이썬을 명령 프롬프트에서 실행하는 방법

파이썬은 어떻게 명령줄에서 실행될까?

파이썬을 실행하고 나서 cmd라 불리는 명령 프롬프트를 열고 python 이라 입력하고 엔터를 치면 아래와 같이 대화형 쉘 형식으로 파이썬 해석기가 실행된다.

파이썬 대화형 쉘(python.exe)

사실 보통은 이게 실행이 안될 때 왜 안되지? 라고 생각하기는 쉬워도 잘 될 때는 왜되지? 라고 생각해보지는 않는다. 예를 들어 구글 크롬을 설치했다고 하자. 우리는 늘 시작메뉴나 바탕화면의 아이콘을 사용해서 크롬을 열고 있지만, 크롬 그 자체 역시 윈도우용 프로그램의 실행파일이며, 이러한 바로가기 아이콘들은 해당 실행파일과 연결되어 있어서 이를 더블클릭하는 것은 결과적으로 해당 exe 파일을 실행하는 것과 동일한 효과를 낸다.

그럼에도 불구하고 명령줄에서 chrome이라고 입력하고 엔터친다고 크롬이 구동되지는 않는다. 우리는 아래와 같은 허망한 에러 메시지들만 보게 된다.

허무하다….

명령줄의 비밀

여기에는 작은 비밀이 숨어 있다. 우리가 흔히 말하는 도스창 혹은 명령 프롬프트는 cmd.exe라는 도스 시절의 command.com 과 비슷한 쉘을 실행하는 상태이고, 이 때의 동작은 여전히 도스 시절의 명령체계와 동일하다.

내부명령과 외부 명령

명령줄에서 실행되는 명령은 크게 내부 명령와 외부 명령으로 나누어진다. 내부 명령은 쉘 자체가 지원해주는 명령으로 dir, cd, copy, del, ren 등과 같은 것들이 있다. 이 기능들은 cmd.exe 에 내장된 것으로 해당 명령을 실행하는데에는 별도의 프로그램이 필요없는 것들이다.

반대로 외부명령은 수행되는데 별도의 실행파일이 필요한 것으로, 별도의 exe 파일 그 자체의 이름이 외부명령이다. 기본적으로 외부명령을 호출하면, 쉘은 이 명령에 해당하는 프로그램 파일이 어디있는지 알고 있어야 한다. 위에서 살펴본 구글 크롬의 경우에는 쉘이 chrome.exe 파일이 어디 있는지 알 수 없으므로 실행하지 못하고 오류가 난다. 만약 크롬 실행파일의 전체 경로를 알려준다면? 명령줄에서 크롬 창을 띄우는 것이 얼마든지 가능하다.

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"

아니면 직접 해당 프로그램의 설치 파일이 있는 곳으로 이동해서, chrome 이라고 입력해서 엔터치는 것도 한가지 방법이 될 수 있다.

환경변수, PATH

하지만 기본적으로 모든 실행파일의 경로를 일일이 다 기억하는 것도, 매번 실행할 때마다 경로를 친절하게 다 입력하는 것도 너무 불편하다. 그래서 쉘에서는 PATH 라고하는 환경 변수를 제공한다. 이 환경 변수에 자주 쓰는 명령들이 속한 디렉토리 경로를 집어 넣으면 현재 디렉토리 위치가 어디든 상관없이, 외부 명령들을 내부 명령처럼 불러다 쓸 수 있다.

윈도에서는 기본적으로 C:\WindowsC\Windows\System32 의 경로가 PATH에 포함되어 있다. 메모장 같은 경우의 앱은 이 폴더내에 들어있기 때문에 쉘 어디서든 notepad 파일이름 과 같이 실행하여 특정한 파일을 편집할 수 있다. (보통 hosts 파일을 편집해야 할 때 이 방법을 많이 쓴다.)

기본적으로 파이썬을 설치하면 PATH 환경변수에 파이썬의 설치 경로가 추가된다. 이를 확인해보려면 명령프롬프트를 열고 path라고 입력한다음 엔터치면 다음과 같은 식으로 Python 어쩌구하는 부분이 출력될 것이다.

d:\temp>path
PATH=.......;C:\python36\;C:\python36\scripts\;........

여기서 C:\python36는 파이썬 인터프리터인 python.exe가 설치되어 있는 곳이고, C:\Python36\Scripts는 그외 파이썬의 부가패키지의 실행파일들이 설치된다. 다른 패키지를 내려받고 설치하도록 도와주는 pip같은 것들이 여기에 설치된다고 보면 된다.

윈도 환경변수 PATH는 실행파일이 있는 위치를 지정하여, 실행파일의 전체 경로를 적지 않고도 해당 파일이 실행될 수 있도록 한다.

파이썬이 정상적으로 설치되었다면 파이썬의 설치경로가 PATH에 포함되어 있을 것이고 파이썬 스크립트를 다음과 같이 실행할 수 있다. 예를 들어  D:\temp 라는 폴더 내에 mycalc.py라는 파일이 있을 때, 명령줄에서는 다음과 같이 이 파일을 실행해볼 수 있다.

d:\temp> python mycalc.py 1 + 3
4
# 이 때 mycalc.py 는 d:\temp\ 에 위치한다.

OSX나 리눅스에서는 보통 기본적으로 파이썬이 설치되어 있고, 주로 /usr/bin/python이나 /usr/local/bin/python 등의 경로로 설치되어 있다.

자, 이제 명령줄에서 어떤식으로 프로그램이 실행되는지 감이 오시는지? 코딩을 연습하다보면 이런 식으로 터미널(혹은 쉘)을 많이 쓰게 되는데, 이 경우에 명령줄에서 바로 실행해야 하는 프로그램들은 이와 같이 설치시에 PATH에 추가하는 옵션을 주어야 한다. 만약 그렇지 않고 실행한 경우에는 윈도의 환경 변수를 직접 편집하여 PATH에 자주 쓰는 프로그램 설치 폴더를 지정하여 줄 수 있다. 대표적으로 vim 이라든지 gcc와 같은 C 컴파일러들이 여기에 속한다.

참고: 환경변수 편집 툴 추천 – RapidEE

윈도에서 환경변수를 편집하는 UI는 참으로 거지같기 때문에 직접 컴퓨터 등록 정보를 열어서 하는 것은 위험하고, 최소한 편집기에 복사했다가 편집해서 다시 붙여넣어주는 방식으로 교체해야 한다. 개인적으로는 RapidEE라는 윈도 환경 변수 편집용 툴을 강력추천한다.

특별부록  – py, pyw

환경변수 설정에 어려움을 겪는 사람들이 많아서인지, 요즘의 파이썬 설치 패키지에는 py.exe라는 파일이 포함되어 있다. 이 파일은 파이썬 인터프리터를 실행해주는 역할을 하며, C:\Windows 폴더에 들어가게 된다. 보통 이 경로는 기본적으로 PATH에 포함되어 있기 때문에 다음과 같이 실행해도 된다.

d:\temp> py mycalc.py 1 + 3
4

py.exe는 특히 파이썬이 2개 이상 버전으로 등록된 경우에 유용하게 쓸 수 있다. 예를 들어 파이썬 2.7과 3.4가 동시에 설치되어 있고, 이중 2.7이 PATH에 포함되어 있다면,

  • py : 디폴트 설정 버전을 실행한다.
  • py -2 : Python 2.x 대 버전을 실행한다.
  • py -3 : Python 3.x 대 버전을 실행한다.

고급 팁 : 파이썬 스크립트를 실행파일처럼 외부 명령으로 실행하기

 

직접 작성한 파이썬 소스코드를 실행해보려면 python.exe 프로그램에 인자값으로 파일 이름을 전달하여 실행할 수 있음을 위에서 살펴보았다. 하지만 파이썬 스크립트를 실행할 때 매번 앞에 python 이나 py를 붙이는 것도 귀찮을 때가 있다. 배치 파일 ( .bat)같은걸 만들어서 PATH 내 의 어느 폴더에 만들어 놓고 쓰는 사람도 있을 수 있겠지만, 이것도 번거롭다. 그런데 리눅스나 유닉스에서는 이런 스크립트를 실행하는 방식이 조금 특이하다. 즉 스크립트 번역기를 소스 내에서 지정해 놓으면, 스크립트 소스 자체가 실행파일처럼 실행될 수 있는 기능이 있다.

리눅스나 OSX에서는 파이썬 소스코드 맨 첫줄에 #! python, #!/usr/bin/python 등으로 인터프리터 명령이나 경로를 지정해놓으면, 해당 인터프리터로 알아서 실행된다. 이는 펄, 루피, JS 스크립트등 모든 스크립트에 대해서 공통적으로 지원되는 기능이다.

PATHEXT 환경변수 – 실행가능한 파일의 확장자를 정의한다.

윈도 환경변수중에는 PATHEXT라는게 있는데, 이는 특정 확장자를 가진 파일을 실행가능한 것으로 인식하게끔한다. 윈도 명령행에서 각 환경변수는 %를 앞뒤로 붙인 이름으로 인식한다. 실제로 쉘 상에서 확인해볼 수도 있다.

d:\temp>echo %PATHEXT%
.COM;.EXE;.BAT;.CMD;.VBS..... ;.PYW;.PY

위 와 같은 식으로 .PYW, .PY가 등록되어 있다면 mycalc.py 라는 스크립트는 다음과 같이 실행할 수 있다는 의미이다.

d:\temp> mycalc.py 2 + 3
....?

이렇게 까지해서 실행이 되면 좋겠다. 하지만 모든 시스템의 상태가 동일하다고 보장할 수는 없으니 실행이 안되는 사람도 있을 수 있다. 물론, 많은 경우에는 py 명령이면 충분하겠지만, 스크립트 이름만으로 실행하고픈 사람이라면 아마 파이썬으로 여러가지 도구를 만들어서 쓰려는 사람일것이니, 여기서 조금 더 자세히 파고 들어가 보겠다.

assoc, ftype 명령

윈도에서는 특정 파일의 확장자가 어떤 파일인지를 식별하고, 어떻게 실행할 것인지를 따로 레지스트리에  저장해서 관리한다. 명령줄에서 정보들을 액세스하고 변경할 수 있는 명령이 assoc, ftype이다. (외부명령이다.)

우리는 이제 이 명령을 이용해서 다음과 같은 사항을 시스템에게 단단히 알려줄 셈이다.

  1. .py로 끝나는 파일은 실행 가능한 외부명령 파일이다. (이 정보는 PATHEXT 환경 변수를 통해서 알려준다.)
  2. .py로 끝나는 파일은 PythonFile이라는 형식의 파일이다. ( assoc 명령을 이용해서 등록한다.)
  3. PythonFile 이라는 형식의 파일은 python.exe 프로그램을 사용하여 실행시킬 것이다. ( ftype 명령을 이용해서 등록한다.)

assoc 명령 사용하기

assoc 명령은 특정 확장자 파일이 어떤 형식인지를 시스템으로부터 알아내거나 이를 변경할 수 있다. 파이썬과 관련된 확장자와 그 파일타입은 다음과 같은 값이 있다.

  • .py=Python.File
  • .pyc=Python.CompiledFile
  • .pyw=Python.NoConFile

이 명령을 어떻게 쓰는지 궁금하면 /?를 붙여서 실행해본다. 물론 MS프로그램의 도움말은 30년전부터 그다지 도움은 되지 않는게 대부분이다.

d:\temp>assoc /?
파일 확장명 연결을 보여주거나 수정합니다.

ASSOC [.확장명=[파일 유형]]

  .확장명   파일 유형과 연결할 파일 확장명을 지정합니다.
  파일 유형 파일 확장명과 연결할 파일 유형을 지정합니다.

현재 파일 연결을 보려면 매개 변수 없이 'ASSOC'라고 입력합니다.
ASSOC가 파일 확장명만 가지고 불려진 경우, 해당 파일 확장명에 대한 현재
파일 연결을 보여줍니다. 파일 유형에 대해 아무 것도 지정하지 않으면
명령은 해당 파일 확장명의 연결을 제거합니다.

이제 assoc 명령을 아무런 인자없이 실행하면 전체 리스트를 보여준다.

d:\temp> assoc
...
...

근데 양이 엄청 많을 것이다. 뭐 인내심이 강한 사람이라면 assoc | more와 같이 실행해서 하나하나 찾는 방법이 있겠지만, 우리는 바쁘니까 다음과 같이 실행한다. (msys32 같은 명령줄 도구 모음을 가지고 있는 사람이라면, findstr대신에 grep을 쓸 수도 있다.)

d:\temp>assoc | findstr ".py"
.py=Python.File
.pyc=Python.CompiledFile
.pyo=Python.CompiledFile
.pys=pysFile
.pyw=Python.NoConFile

만약 여기에 .py=Python.File이 없다면? 아래와 같이 연결을 만들어준다.

d:\temp>assoc .py=Python.File
.py=Python.File

####   ftype 명령 사용하기

이제 다음은 ftype으로 해당 타입의 파일을 어떻게 실행할 것인지를 정해준다. 역시 ftype은 assoc과 비슷한 사용법을 가지고 있다. 먼저 파일 타입 연결을 확인한다. 아래 결과는 제대로 설정되었을 때의 내용이다.

d:\temp>ftype | findstr "python"
Python.CompiledFile="C:\Python36\python.exe" "%1" %*
Python.File="C:\Python36\python.exe" "%1" %*
Python.NoConFile="C:\Python36\python.exe" "%1" %*

대충 위외 비슷한 값이 나오면 된다. Python.File="C:\Python36\python.exe" "%1" %*이 부분이 가장 중요하다. 만약 없거나 다르게 되어 있다면 수정하도록하자. 단, 여기서 C:\Python36는 파이썬의 정확한 설치 경로여야 한다. 파이썬을 다른 데 설치했으면 알아서 잘 변경하도록 하자.

d:\temp>ftype Python.File="C:\Python36\python.exe" "%1" %*
Python.File="C:\Python34\python.exe" "%1" %*

비상 대책 : 레지스트리

여기까지 했을 때 잘되면 좋은데, 그래도 안되는 경우가 있다. 👿

윈도에서는 이상하게 파이썬의 실행과 관련된 내용을 표준 확장자 처리 영역이 아니라 별도의 파이썬 해석기 옵션으로 넣는 경우가 종종 있다. (만일 파이썬의 매우 구 버전부터 차츰차츰 업그레이드해서 써온 사람이라면 이렇게 될 확률이 크다.)

그래서 이게 안되면 레스트리 편집을 해야하는데, 여기서는 힌트만 주겠다. 왜냐면 레지스트리 편집을 부주의하게 하는 경우, 시스템이 정상작동하지 않는 불상사가 생길 수 있는데 그 책임을 내가 대신 져줄 수는 없기 때문이다. “나는 레지스트리를 잘 모른다” 하는 사람은 그냥 좀 불편해도 py 명령 정도로 만족하고 지내도록 하자.

  1. HKEY_CLASSES_ROOT\.py 키의 값이 Python.File 인지 확인한다.
  2. HKEY_CLASSES_ROOT\Applications\python.exe\shell\open\command 키의 값이 "C:\Python34\python.exe" "%1" %*인지 확인한다.
  3. 일부 시스템의 경우에는 HKEY_CLASSES_ROOT\py_auto_file\shell\open\command 이 키를 참조하여 실행하는 경우가 있다. 역시 "C:\Python36\python.exe" "%1" %*라는 값이 들어가 있는지 확인한다.

어쨌든 길고 복잡한 여정을 넘어서 여기까지 잘 도착했다면, 이제 c:\python36\python.exe mycalc.py 1 + 3이라고 입력해서 실행해야 했던 파일은 그냥 아래와 같이 가장 간단한 형태로 실행할 수 있게 된다.

d:\temp> mycalc 1 + 3
4

이제  파이썬 스크립트를 일반 명령처럼 쓸 수 있게 되었으니,  자신이 생각하기에 유용하다 생각되는 스크립트는 어디 한 군데 몰아놓고 PATH에 추가해두면 유용하게 쓸 수 있다.

나의 경우, 명령줄에서 간단한 수식을 계산할 수 있는 calc.py나 우리 동네 대기 오염 정보를 가져와서 출력해주는 스크립트, PIP로 설치한 모든 패키지들을 한꺼번에 업그레이드하는 등의 여러 노가다를 해소해주는 스크립트들을 이런식으로 만들어서 사용하고 있다.

긴 이름의 옵션을 파싱하는 C함수, getopt_long()

긴 이름 옵션 파싱함수

getopt() 함수는 비교적 사용이 쉬운데, 보통 명령행 유틸리티들은 옵션을 보다 명확하게 인지할 수 있는 긴 이름의 옵션들을 지원한다. 예를 들어 출력파일을 결정할 때 -o outfile로 쓰는 대신 --output outfile로 쓰게끔 허용하는 것이다. 이 기능은 getopt_long()이라는 함수를 통해 지원할 수 있다. 긴 이름 옵션은 하나의 문자열에 망라하기 어려우므로 별도의 구조체를 사용하여 옵션 정보를 마련해두고 이 구조체의 배열을 사용하는 방식으로 처리한다. 그러면서 인터페이스는 좀 달라지지만, 사용하는 방식은 거의 유사하다고 보면 된다.

긴 이름의 옵션을 파싱하는 C함수, getopt_long() 더보기