Python中有没有类似于Ruby的StringScanner?

2 投票
7 回答
4853 浏览
提问于 2025-04-15 16:07

有没有一个Python的类,跟Ruby的StringScanner类类似?我可以自己动手做一个,但如果已经有现成的,我就不想重复造轮子了。

7 个回答

4

在Python中,没有完全像Ruby的StringScanner那样的东西。当然,自己动手做一个是很简单的:

import re

class Scanner(object):
    def __init__(self, s):
        self.s = s
        self.offset = 0
    def eos(self):
        return self.offset == len(self.s)
    def scan(self, pattern, flags=0):
        if isinstance(pattern, basestring):
            pattern = re.compile(pattern, flags)
        match = pattern.match(self.s, self.offset)
        if match is not None:
            self.offset = match.end()
            return match.group(0)
        return None

这里还有一个互动使用的例子

>>> s = Scanner("Hello there!")
>>> s.scan(r"\w+") 
'Hello'
>>> s.scan(r"\s+") 
' '
>>> s.scan(r"\w+")
'there'
>>> s.eos()
False
>>> s.scan(r".*")
'!'
>>> s.eos()
True
>>> 

不过,对于我做的工作,我通常会一次性写好正则表达式,然后用分组来提取需要的字段。或者如果遇到更复杂的情况,我会写一个临时的分词器,或者使用PyParsing或PLY来帮我分词。我觉得自己不会用像StringScanner这样的东西。

10

有趣的是,在 re 模块里,有一个没有文档说明的 Scanner 类:

import re

def s_ident(scanner, token): return token
def s_operator(scanner, token): return "op%s" % token
def s_float(scanner, token): return float(token)
def s_int(scanner, token): return int(token)

scanner = re.Scanner([
    (r"[a-zA-Z_]\w*", s_ident),
    (r"\d+\.\d*", s_float),
    (r"\d+", s_int),
    (r"=|\+|-|\*|/", s_operator),
    (r"\s+", None),
    ])

print scanner.scan("sum = 3*foo + 312.50 + bar")

根据 讨论 的内容来看,这个类似乎是作为实验代码留下来的,或者是给其他人作为起点的。

1

看起来这和 re.split( pattern, string ) 有点像。

http://docs.python.org/library/re.html

http://docs.python.org/library/re.html#re.split

撰写回答