Development Tip

파이썬의 sscanf

yourdevel 2020. 12. 13. 11:13
반응형

파이썬의 sscanf


sscanf()파이썬에서 와 동등한 것을 찾고 있습니다. /proc/net/*CI에서 파일 을 구문 분석 하고 싶습니다.

int matches = sscanf(
        buffer,
        "%*d: %64[0-9A-Fa-f]:%X %64[0-9A-Fa-f]:%X %*X %*X:%*X %*X:%*X %*X %*d %*d %ld %*512s\n",
        local_addr, &local_port, rem_addr, &rem_port, &inode);

처음에는을 사용하려고 생각 str.split했지만 주어진 문자로 분할되지 않고 sep전체 문자열로 나뉩니다 .

>>> lines = open("/proc/net/dev").readlines()
>>> for l in lines[2:]:
>>>     cols = l.split(string.whitespace + ":")
>>>     print len(cols)
1

위에서 설명한대로 17을 반환해야합니다.

sscanf(RE가 아님)에 해당하는 Python 또는 내가 알지 못하는 문자 범위를 분할하는 표준 라이브러리의 문자열 분할 함수가 있습니까?


파이썬에는 sscanf동등한 내장 기능 이 없으며 , 대부분의 경우 실제로 문자열로 직접 작업하거나 정규 표현식을 사용하거나 구문 분석 도구를 사용하여 입력을 구문 분석하는 것이 훨씬 더 합리적입니다.

아마도 C 번역에 대부분 유용 할 것입니다. 사람들은 다음 sscanf과 같은 모듈을 구현했습니다 . http://hkn.eecs.berkeley.edu/~dyoo/python/scanf/

이 특별한 경우 여러 분할 문자를 기반으로 데이터를 분할하려는 경우 re.split실제로 올바른 도구입니다.


도 있습니다 parse모듈.

parse()format()(Python 2.6 이상의 최신 문자열 형식 지정 함수) 의 반대 방향으로 설계되었습니다 .

>>> from parse import parse
>>> parse('{} fish', '1')
>>> parse('{} fish', '1 fish')
<Result ('1',) {}>
>>> parse('{} fish', '2 fish')
<Result ('2',) {}>
>>> parse('{} fish', 'red fish')
<Result ('red',) {}>
>>> parse('{} fish', 'blue fish')
<Result ('blue',) {}>

내가 C 분위기 일 때, 나는 보통 scanf와 같은 행동을 위해 zip과 list comprehensions를 사용합니다. 이렇게 :

input = '1 3.0 false hello'
(a, b, c, d) = [t(s) for t,s in zip((int,float,strtobool,str),input.split())]
print (a, b, c, d)

더 복잡한 형식 문자열의 경우 정규 표현식을 사용해야합니다.

import re
input = '1:3.0 false,hello'
(a, b, c, d) = [t(s) for t,s in zip((int,float,strtobool,str),re.search('^(\d+):([\d.]+) (\w+),(\w+)$',input).groups())]
print (a, b, c, d)

또한 변환하려는 모든 유형에 대한 변환 함수가 필요합니다. 예를 들어 위에서 다음과 같은 것을 사용했습니다.

strtobool = lambda s: {'true': True, 'false': False}[s]

re모듈을 사용하여 다양한 문자로 분할 할 수 있습니다 .

>>> import re
>>> r = re.compile('[ \t\n\r:]+')
>>> r.split("abc:def  ghi")
['abc', 'def', 'ghi']

명명 된 그룹을re 사용하여 모듈로 구문 분석 할 수 있습니다 . 하위 문자열을 실제 데이터 유형 (예 :)으로 구문 분석하지 않지만 문자열을 구문 분석 할 때 매우 편리합니다.int

다음의 샘플 라인이 제공됩니다 /proc/net/tcp.

line="   0: 00000000:0203 00000000:0000 0A 00000000:00000000 00:00000000 00000000     0        0 335 1 c1674320 300 0 0 0"

sscanf 예제를 변수로 모방 한 예는 다음과 같습니다.

import re
hex_digit_pattern = r"[\dA-Fa-f]"
pat = r"\d+: " + \
      r"(?P<local_addr>HEX+):(?P<local_port>HEX+) " + \
      r"(?P<rem_addr>HEX+):(?P<rem_port>HEX+) " + \
      r"HEX+ HEX+:HEX+ HEX+:HEX+ HEX+ +\d+ +\d+ " + \
      r"(?P<inode>\d+)"
pat = pat.replace("HEX", hex_digit_pattern)

values = re.search(pat, line).groupdict()

import pprint; pprint values
# prints:
# {'inode': '335',
#  'local_addr': '00000000',
#  'local_port': '0203',
#  'rem_addr': '00000000',
#  'rem_port': '0000'}

기본 scanf http://code.activestate.com/recipes/502213-simple-scanf-implementation/ 을 구현하는 ActiveState 레시피가 있습니다 .


업데이트 : 정규식 모듈에 대한 Python 설명서 re에는 scanf 시뮬레이션 섹션이 포함되어 있습니다.

https://docs.python.org/2/library/re.html#simulating-scanf


you can turn the ":" to space, and do the split.eg

>>> f=open("/proc/net/dev")
>>> for line in f:
...     line=line.replace(":"," ").split()
...     print len(line)

no regex needed (for this case)


Upvoted orip's answer. I think it is sound advice to use re module. The Kodos application is helpful when approaching a complex regexp task with Python.

http://kodos.sourceforge.net/home.html


If the separators are ':', you can split on ':', and then use x.strip() on the strings to get rid of any leading or trailing whitespace. int() will ignore the spaces.


There is a Python 2 implementation by odiak.

참고URL : https://stackoverflow.com/questions/2175080/sscanf-in-python

반응형