# `shlex` — 간단한 어휘 분석

소스 코드: Lib/shlex.py

`shlex` 클래스를 사용하면 유닉스 셸과 유사한 간단한 구문에 대한 어휘 분석기를 쉽게 작성할 수 있습니다. 이것은 미니 언어를 작성하거나 (예를 들어 파이썬 응용 프로그램을 위한 실행 제어 파일에서), 인용된 문자열을 구문 분석할 때 유용합니다.

The `shlex` module defines the following functions:

shlex.split(s, comments=False, posix=True)

  셸과 비슷한 문법을 사용하여 문자열 s를 분할합니다. comments가 `False`(기본값)이면, 지정된 문자열의 주석 구문 분석이 비활성화됩니다 (`shlex` 인스턴스의 `commenters` 어트리뷰트를 빈 문자열로 설정합니다). 이 함수는 기본적으로 POSIX 모드로 작동하지만, posix 인자가 거짓이면 비 POSIX 모드를 사용합니다.

  버전 3.12에서 변경: s 인자에 `None`을 전달하면 이제 `sys.stdin`을 읽는 대신 예외를 일으킵니다.

shlex.join(split_command)

  리스트 split_command의 토큰을 이어붙이고 문자열을 반환합니다. 이 함수는 `split()`의 역함수입니다.

      >>> from shlex import join
      >>> print(join(['echo', '-n', 'Multiple words']))
      echo -n 'Multiple words'

  반환된 값은 주입 취약점(injection vulnerabilities)으로부터 보호하기 위해 셸 이스케이프 처리됩니다 (`quote()`를 참조하십시오).

  Added in version 3.8.

shlex.quote(s)

  셸 이스케이프 된 문자열 s를 반환합니다. 반환된 값은 (리스트를 사용할 수 없는 경우) 셸 명령 줄에서 하나의 토큰으로 안전하게 사용할 수 있는 문자열입니다.

  경고

  The `shlex` module is only designed for Unix shells.

  The `quote()` function is not guaranteed to be correct on non-POSIX compliant shells or shells from other operating systems such as Windows. Executing commands quoted by this module on such shells can open up the possibility of a command injection vulnerability.

  Consider using functions that pass command arguments with lists such as `subprocess.run()` with `shell=False`.

  이 관용구는 안전하지 않습니다:

      >>> filename = 'somefile; rm -rf ~'
      >>> command = 'ls -l {}'.format(filename)
      >>> print(command)  # executed by a shell: boom!
      ls -l somefile; rm -rf ~

  `quote()`를 사용하면 보안 허점을 메꿀 수 있습니다:

      >>> from shlex import quote
      >>> command = 'ls -l {}'.format(quote(filename))
      >>> print(command)
      ls -l 'somefile; rm -rf ~'
      >>> remote_command = 'ssh home {}'.format(quote(command))
      >>> print(remote_command)
      ssh home 'ls -l '"'"'somefile; rm -rf ~'"'"''

  인용(quoting)은 유닉스 셸과 `split()`과 호환됩니다:

      >>> from shlex import split
      >>> remote_command = split(remote_command)
      >>> remote_command
      ['ssh', 'home', "ls -l 'somefile; rm -rf ~'"]
      >>> command = split(remote_command[-1])
      >>> command
      ['ls', '-l', 'somefile; rm -rf ~']

  Added in version 3.3.

The `shlex` module defines the following class:

class shlex.shlex(instream=None, infile=None, posix=False, punctuation_chars=False)

  `shlex` 인스턴스나 서브 클래스 인스턴스는 어휘 분석기 객체입니다. 존재할 때 초기화 인자는 문자를 어디에서 읽을지를 지정합니다. `read()`와 `readline()` 메서드가 있는 파일/스트림류 객체이거나 문자열이어야 합니다. 인자가 없으면 `sys.stdin`에서 입력을 받습니다. 두 번째 선택적 인자는 파일명 문자열이며, `infile` 어트리뷰트의 초깃값을 설정합니다. instream 인자가 생략되거나 `sys.stdin`과 같으면, 이 두 번째 인자의 기본값은 “stdin”입니다. posix 인자는 작동 모드를 정의합니다: posix가 참이 아닐 때 (기본값), `shlex` 인스턴스는 호환 모드에서 작동합니다. POSIX 모드에서 작동할 때, `shlex`는 가능한 한 POSIX 셸 구문 분석 규칙에 가깝도록 시도합니다. punctuation_chars 인자는 동작을 실제 셸이 구문 분석하는 방식에 더 가깝게 만드는 방법을 제공합니다. 이것은 여러 종류의 값을 취할 수 있습니다: 기본값 `False`는 파이썬 3.5와 이전 버전에서의 동작을 유지합니다. `True`로 설정되면, 문자 `();<>|&`의 구문 분석이 변경됩니다: 이러한 문자(구두(punctuation) 문자로 간주합니다)의 모든 연속은 단일 토큰으로 반환됩니다. 비어 있지 않은 문자열로 설정하면, 해당 문자는 구두(punctuation) 문자로 사용됩니다. punctuation_chars에 나타나는 `wordchars` 어트리뷰트의 문자는 `wordchars`에서 제거됩니다. 자세한 정보는 셸과의 호환성 향상을 참조하십시오. punctuation_chars는 `shlex` 인스턴스 생성 시에만 설정할 수 있으며 나중에 수정할 수 없습니다.

  버전 3.6에서 변경: punctuation_chars 매개 변수가 추가되었습니다.

더 보기

모듈 `configparser`

  윈도우 `.ini` 파일과 유사한 구성 파일 구문 분석기.

## shlex 객체

`shlex` 인스턴스에는 다음과 같은 메서드가 있습니다:

shlex.get_token()

  토큰을 반환합니다. `push_token()`을 사용하여 토큰이 스택(stack) 되었으면, 스택에서 토큰을 팝(pop) 합니다. 그렇지 않으면, 입력 스트림에서 하나를 읽습니다. 읽기가 즉시 파일 끝을 만나면, `eof`가 반환됩니다 (POSIX 모드가 아니면 빈 문자열 (`''`), POSIX 모드이면 `None`).

shlex.push_token(str)

  인자를 토큰 스택으로 푸시(push)합니다.

shlex.read_token()

  원시 토큰을 읽습니다. 푸시백 스택을 무시하고, 소스 요청(source requests)을 해석하지 않습니다. (이것은 일반적으로 유용한 진입점이 아니며, 단지 완전성을 위해 여기에서 설명합니다.)

shlex.sourcehook(filename)

  `shlex`가 소스 요청(아래 `source`를 참조하십시오)을 감지할 때 이 메서드에는 다음 토큰이 인자로 제공되고 파일명과 열린 파일류 객체로 구성된 튜플을 반환해야 합니다.

  일반적으로, 이 메서드는 먼저 인자에서 인용(quotes)을 제거합니다. 결과가 절대 경로명이거나 유효한 이전 소스 요청이 없거나 이전 소스가 스트림(가령 `sys.stdin`)이면 결과는 그대로 유지됩니다. 그렇지 않으면, 결과가 상대 경로명이면 소스 포함 스택에서 파일 바로 앞에 있는 파일의 이름의 디렉터리 부분을 앞에 붙입니다 (이 동작은 C 전처리기가 `#include "file.h"`를 처리하는 방식과 유사합니다).

  조작 결과는 파일명으로 취급되고, 튜플의 첫 번째 구성 요소로 반환되며, 이것에 `open()`이 호출되어 두 번째 구성 요소를 산출합니다. (참고: 이것은 인스턴스 초기화의 인자 순서와 반대입니다!)

  이 훅은 디렉터리 검색 경로, 파일 확장자 추가 및 기타 네임 스페이스 해킹을 구현하는 데 사용할 수 있도록 노출됩니다. 해당 ‘닫기’ 훅은 없지만, shlex 인스턴스는 소스 입력 스트림이 EOF를 반환할 때 그것의 `close()` 메서드를 호출합니다.

  소스 스태킹을 더 명시적으로 제어하려면, `push_source()`와 `pop_source()` 메서드를 사용하십시오.

shlex.push_source(newstream, newfile=None)

  입력 소스 스트림을 입력 스택으로 푸시합니다. filename 인자가 지정되면 나중에 에러 메시지에 사용할 수 있습니다. 이것은 `sourcehook()` 메서드에 의해 내부적으로 사용되는 것과 같은 메서드입니다.

shlex.pop_source()

  마지막으로 푸시 된 입력 소스를 입력 스택에서 팝 합니다. 이는 어휘 분석기가 스택 된 입력 스트림에서 EOF에 도달할 때 내부적으로 사용되는 것과 같은 메서드입니다.

shlex.error_leader(infile=None, lineno=None)

  이 메서드는 유닉스 C 컴파일러 에러 레이블 형식으로 에러 메시지 리더를 생성합니다; 형식은 `'"%s", line %d: '`이며, 여기서 `%s`는 현재 소스 파일의 이름으로 치환되고 `%d`는 현재 입력 줄 번호로 치환됩니다 (선택적 인자를 사용하여 이를 재정의할 수 있습니다).

  This convenience is provided to encourage `shlex` users to generate error messages in the standard, parseable format understood by Emacs and other Unix tools.

`shlex` 서브 클래스의 인스턴스에는 어휘 분석을 제어하거나 디버깅에 사용할 수 있는 일부 공용 인스턴스 변수가 있습니다:

shlex.commenters

  주석을 시작하는 것으로 인식되는 문자열. 주석 시작부터 줄 끝까지의 모든 문자는 무시됩니다. 기본적으로 `'#'` 만 포함합니다.

shlex.wordchars

  다중 문자 토큰에 누적될 문자들의 문자열. 기본적으로, 모든 ASCII 영숫자와 밑줄이 포함됩니다. POSIX 모드에서는, 라틴-1 집합의 악센트 부호 문자도 포함됩니다. `punctuation_chars`가 비어 있지 않으면, 파일명 명세와 명령 줄 매개 변수에 나타날 수 있는 문자 `~-./*?=`도 이 어트리뷰트에 포함되며, `punctuation_chars`에 있는 문자는 `wordchars`에 있으면 제거됩니다. `whitespace_split`이 `True`로 설정되면, 이것은 효과가 없습니다.

shlex.whitespace

  공백으로 간주하여 건너뛸 문자들. 공백은 토큰의 경계를 만듭니다. 기본적으로, 스페이스, 탭, 줄 바꿈 및 캐리지 리턴이 포함됩니다.

shlex.escape

  이스케이프로 간주하는 문자들. POSIX 모드에서만 사용되며, 기본적으로 `'\'` 만 포함합니다.

shlex.quotes

  문자열 인용으로 간주하는 문자들. 같은 인용을 다시 만날 때까지 토큰이 누적됩니다 (따라서, 다른 인용 유형은 셸에서와같이 서로를 보호합니다). 기본적으로, ASCII 작은따옴표와 큰따옴표가 포함됩니다.

shlex.escapedquotes

  `escape`에 정의된 이스케이프 문자를 해석하는 `quotes`의 문자들. 이것은 POSIX 모드에서만 사용되며, 기본적으로 `'"'` 만 포함합니다.

shlex.whitespace_split

  `True`이면, 토큰은 공백으로만 분할됩니다. 예를 들어, `shlex`로 명령 줄을 구문 분석하고 셸 인자와 유사한 방식으로 토큰을 가져오는 데 유용합니다. `punctuation_chars`와 함께 사용하면, 토큰은 그 문자들 외에도 공백으로 분할됩니다.

  버전 3.8에서 변경: `punctuation_chars` 어트리뷰트가 `whitespace_split` 어트리뷰트와 호환되었습니다.

shlex.infile

  클래스 인스턴스화 시점에 처음 설정되거나 이후 소스 요청으로 스택 된 현재 입력 파일의 이름. 에러 메시지를 구성할 때 이를 조사하는 것이 유용할 수 있습니다.

shlex.instream

  이 `shlex` 인스턴스가 문자를 읽고 있는 입력 스트림.

shlex.source

  이 어트리뷰트는 기본적으로 `None`입니다. 문자열을 대입하면, 해당 문자열은 여러 셸의 `source` 키워드와 유사한 어휘 수준 포함 요청으로 인식됩니다. 즉, 바로 다음 토큰이 파일명으로 열리고 그 스트림에서 입력을 EOF까지 취합니다, 이 시점에서 해당 스트림의 `close()` 메서드가 호출되고 입력 소스는 다시 원래 입력 스트림이 됩니다. 소스 요청은 임의의 수준 깊이로 스택 될 수 있습니다.

shlex.debug

  이 어트리뷰트가 숫자이고 `1` 이상이면, `shlex` 인스턴스는 자신의 동작에 대한 자세한 진행 출력을 인쇄합니다. 이것을 사용해야 하면, 세부 사항을 배우기 위해 모듈 소스 코드를 읽을 수 있습니다.

shlex.lineno

  소스 줄 번호 (지금까지 본 줄 넘김 개수에 1을 더한 것).

shlex.token

  토큰 버퍼. 예외를 잡을 때 이를 조사하는 것이 유용 할 수 있습니다.

shlex.eof

  파일 끝을 판단하는 데 사용되는 토큰. POSIX 모드가 아닐 때 빈 문자열 (`''`), POSIX 모드일 때 `None`으로 설정됩니다.

shlex.punctuation_chars

  읽기 전용 프로퍼티. 구두 부호로 간주할 문자들. 구두 부호 문자들은 단일 토큰으로 반환됩니다. 그러나, 아무런 의미 유효성 검사도 수행되지 않음에 유의하십시오: 예를 들어 ‘>>>’는 셸에서 인식되지 않더라도 토큰으로 반환될 수 있습니다.

  Added in version 3.6.

## 구문 분석 규칙

When operating in non-POSIX mode, `shlex` will try to obey the following rules.

- 인용 문자는 단어 내에서 인식되지 않습니다 (`Do"Not"Separate`는 단일 단어 `Do"Not"Separate`로 구문 분석됩니다);

- 이스케이프 문자는 인식되지 않습니다;

- 인용으로 묶인 문자들은 인용 안에 있는 모든 문자의 리터럴 값을 유지합니다;

- 인용을 닫는 것은 단어를 분리합니다 (`"Do"Separate`는 `"Do"`와 `Separate`로 구문 분석됩니다);

- `whitespace_split`가 `False`이면, 단어 문자, 공백 또는 인용으로 선언되지 않은 모든 문자는 단일 문자 토큰으로 반환됩니다. `True`이면, `shlex`는 공백으로 만 단어를 분리합니다;

- EOF는 빈 문자열(`''`)로 알립니다;

- 인용된 경우에도 빈 문자열을 구문 분석할 수 없습니다.

When operating in POSIX mode, `shlex` will try to obey the following parsing rules.

- 인용은 제거되고, 단어를 분리하지 않습니다 (`"Do"Not"Separate"`는 단일 단어 `DoNotSeparate`로 구문 분석됩니다);

- 인용되지 않은 이스케이프 문자(예를 들어 `'\'`)는 다음에 오는 문자의 리터럴 값을 유지합니다;

- `escapedquotes`의 일부가 아닌 인용으로 묶인 문자(예를 들어 `"'"`)는 인용 안에 있는 모든 문자의 리터럴 값을 유지합니다;

- Enclosing characters in quotes which are part of `escapedquotes` (e.g. `'"'`) preserves the literal value of all characters within the quotes, with the exception of the characters mentioned in `escape`. The escape characters retain their special meaning only when followed by the quote in use, or the escape character itself. Otherwise the escape character will be considered a normal character.

- EOF는 `None` 값으로 알립니다;

- 인용된 빈 문자열(`''`)이 허용됩니다.

## 셸과의 호환성 향상

Added in version 3.6.

`shlex` 클래스는 `bash`, `dash` 및 `sh`와 같은 일반적인 유닉스 셸에서 수행하는 구문 분석과 호환됩니다. 이 호환성을 이용하려면, 생성자에서 `punctuation_chars` 인자를 지정하십시오. 기본값은 `False`이며, 3.6 이전 동작을 유지합니다. 그러나, `True`로 설정되면, 문자 `();<>|&`의 구문 분석이 변경됩니다: 이러한 문자의 연속은 단일 토큰으로 반환됩니다. 이것은 셸에 대한 전체 파서로는 부족하지만 (여러 종류의 셀이 있음을 고려할 때, 표준 라이브러리의 범위를 벗어납니다), 이것이 없을 때보다 명령 줄 처리를 더 쉽게 수행할 수 있도록 합니다. 예시하기 위해, 다음 코드 조각에서 차이점을 볼 수 있습니다:

    >>> import shlex
    >>> text = "a && b; c && d || e; f >'abc'; (def \"ghi\")"
    >>> s = shlex.shlex(text, posix=True)
    >>> s.whitespace_split = True
    >>> list(s)
    ['a', '&&', 'b;', 'c', '&&', 'd', '||', 'e;', 'f', '>abc;', '(def', 'ghi)']
    >>> s = shlex.shlex(text, posix=True, punctuation_chars=True)
    >>> s.whitespace_split = True
    >>> list(s)
    ['a', '&&', 'b', ';', 'c', '&&', 'd', '||', 'e', ';', 'f', '>', 'abc', ';',
    '(', 'def', 'ghi', ')']

물론, 셸에 유효하지 않은 토큰이 반환되며, 반환된 토큰에 대해 여러분 자신의 에러 검사를 구현해야 합니다.

punctuation_chars 매개 변수의 값으로 `True`를 전달하는 대신, 특정 문자가 포함된 문자열을 전달하면 구두 부호를 구성하는 문자를 판별하는 데 사용됩니다. 예를 들면:

    >>> import shlex
    >>> s = shlex.shlex("a && b || c", punctuation_chars="|")
    >>> list(s)
    ['a', '&', '&', 'b', '||', 'c']

참고

`punctuation_chars`가 지정되면, `wordchars` 어트리뷰트는 문자 `~-./*?=`로 보강됩니다. 이러한 문자는 파일 이름(와일드카드를 포함해서)과 명령 줄 인자(예를 들어 `--color=auto`)에 나타날 수 있기 때문입니다. 그래서:

    >>> import shlex
    >>> s = shlex.shlex('~/a && b-c --color=auto || d *.py?',
    ...                 punctuation_chars=True)
    >>> list(s)
    ['~/a', '&&', 'b-c', '--color=auto', '||', 'd', '*.py?']

그러나, 가능한 한 가깝게 셸과 일치하려면, `punctuation_chars`를 사용할 때 항상 `posix`와 `whitespace_split`를 사용하는 것이 좋습니다, 이는 `wordchars`를 완전히 무효로 합니다.

최상의 효과를 얻으려면, `punctuation_chars`를 `posix=True`와 함께 설정해야 합니다. (`posix=False`가 `shlex`의 기본값임에 유의하십시오.)