Python:REfO 库的使用

   本文主要介绍 Python 的 REfO 的基本使用方法。

1.1 简介

  REfO,Regular Expressions for Objects。它和 Python 的 re 模块提供相似的功能。但是 REfO 是为对象(object)序列设计的,re 模块是为字符串(string)设计的。

1.2 使用方法

  REfO 的语法与 Python 的 re 有点不同,与 pyparsing 的语法相似。

1.2.1 符号表示
1.2.1.1 普通字符

  普通字符,使用 Literal(),例如:

正则表达式语法
“a”Literal(“a”)
“ab”Literal(“a”) + Literal(“b”)
“1”Literal(“1”)
1.2.1.2 特殊符号

  下面为几个特殊符号的语法表示:

符号语法
?Question()
*Star()
+Plus()
任意字符Any()

  具体如下:

正则表达式语法
“a?”Question(a)
“a*”Star(Literal(“a”))
“(ab)+”Plus(Literal(a) + Literal(b))
“(bb)*?”Star(Literal(b) + Literal(b), greedy=False)

  上面的第 4 个样例中,有一个为 greedy 的参数,当为 False 时,表示非贪婪匹配;当为 True 时,表示贪婪匹配。其中,Star()Plus()Question() 都有这个参数。

1.2.2 匹配操作
1.2.2.1 match()

  函数 match() 只返回第一个匹配。样例如下:

import refo


sentence = "ababab"

a = refo.Literal("a")
b = refo.Literal("b")
pattern = a + b

result = refo.match(pattern, sentence)
start, end = result.span()
print('start={}, end={}'.format(start, end))
print(sentence[start:end])

输出:

start=0, end=2
ab
1.2.2.2 finditer()

  函数 finditer() 返回所有匹配的一个迭代器。样例如下:

import refo


sentence = "ababab"

a = refo.Literal("a")
b = refo.Literal("b")
pattern = a + b

for m in refo.finditer(pattern, sentence):
    start, end = m.span()
    print('start={}, end={}'.format(start, end))
    print(sentence[start:end])

输出:

start=0, end=2
ab
start=2, end=4
ab
start=4, end=6
ab
1.2.3 匹配结果

  函数 match()finditer() 的匹配结果,拥有以下函数:

函数名说明
start()返回匹配结果在对象列表中起始索引
end()返回匹配结果在对象列表中终止索引
span()返回匹配结果在对象列表中起始索引和终止索引

  样例如下:

import refo


sentence = "ababab"

a = refo.Literal("a")
b = refo.Literal("b")
pattern = a + b

result = refo.match(pattern, sentence)
print(result.start())
print(result.end())
print(result.span())

输出:

0
2
(0, 2)

1.3 使用样例

  前面提供样例是使用匹配的字符串(实际上字符串也属于字符序列),无法感受其与 Python 的 re 模块的区别。下面提供一个 官方样例

from refo import finditer, Predicate, Plus

import re
import copy


class Word(object):
    def __init__(self, token, pos):
        self.token = token
        self.pos = pos


class W(Predicate):
    def __init__(self, token=".*", pos=".*"):
        self.token = re.compile(token + "$")
        self.pos = re.compile(pos + "$")
        super(W, self).__init__(self.match)

    def match(self, word):
        """
        采用正则表达式同时匹配对象(word)的字符(token)和词性(pos)
        """
        m1 = self.token.match(word.token)
        m2 = self.pos.match(word.pos)
        return m1 and m2


class Rule(object):
    def __init__(self, condition=None, action=None):
        assert condition and action
        self.condition = condition
        self.action = action

    def apply(self, sentence):
        # 首先进行匹配操作,然后将匹配结果传入对应的操作函数中
        for m in finditer(self.condition, sentence):
            i, j = m.span()
            self.action(sentence[i:j])


def capitalize_name(x):
    """
    将英文单词的首字母大写
    """
    for nnp in x:
        orig = nnp.token
        nnp.token = nnp.token.capitalize()
        print('Capitalized: {} -> {}'.format(orig, nnp.token))


def feet_to_mt(x):
    """
    将英尺转换为米
    """
    number, units = x
    orig_number_token = number.token
    orig_units_token = units.token
    mt = float(number.token) * 0.3048
    number.token = "{0:.2}".format(mt)
    units.token = "mt."
    units.pos = "UNITS_METERS"
    print("feet_to_mt: {} {} -> {} {}".format(
        orig_number_token, orig_units_token, number.token, units.token))


rules = [
    # 规则的目的:将英尺转换为米
    Rule(condition=W(pos="NUMBER") + W(pos="UNITS_FEET"),
         action=feet_to_mt),
    # 规则的目的:将姓名的英文单词的首字母大写
    Rule(condition=Plus(W(token="[^A-Z].*", pos="NNP")),
         action=capitalize_name),
]

sentence = "My|PRP friend|NN john|NNP smith|NNP is|VBZ 2|NUMBER " +\
           "feet|UNITS_FEET taller|JJR than|IN mary|NNP Jane|NNP"

sentence = [Word(*x.split("|")) for x in sentence.split()]
original = copy.deepcopy(sentence)

for rule in rules:
    rule.apply(sentence)

print("From: " + " ".join((w.token for w in original)))
print("To:   " + " ".join((w.token for w in sentence)))

输出:

feet_to_mt: 2 feet -> 0.61 mt.
Capitalized: john -> John
Capitalized: smith -> Smith
Capitalized: mary -> Mary
From: My friend john smith is 2 feet taller than mary Jane
To:   My friend John Smith is 0.61 mt. taller than Mary Jane

  从输出结果,我们可以看到此样例代码的目的:a. 将句子中英尺换算为米;b. 将姓名中的首字母大写。

  从上面我们可以看到,当我们需要匹配非大写字母之类的操作时,使用 Python 的 re 模块来实现会更加简便。

参考:

[1] github
[2] Regular Expressions for Objects

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值