Python 正则分割字符串并提取匹配的记号和关键词

需求是:原字符串内含有特殊记号,比如"V_{CC} = V_{DD}",其中_{CC} 是latex 的下标语法,实际显示出来是下面这样:

V C C = V D D V_{CC} = V_{DD} VCC=VDD

现在要把下标部分提取出来,并把原字符串用这个记号切割开,也就是把原字符串切割成:"V", "CC", " = V", "DD",这种感觉,方便之后单独处理下标。re 库里官方的split 函数太“简陋”了,不太好使。

函数代码

总之代码如下:

import re
from typing import Union, List, Tuple, Optional

def text_find_and_split(pattern: Union[str, re.Pattern], text: str) -> List[Tuple[str, Optional[re.Match]]]:
    '''
    将字符串按正则匹配分割,返回被分割的字符串片段和匹配结果,匹配的片段会从原字符串中被整体切割出去。
    
    比如:原字符串: "AAAA $01$ BBBB $02$ CCCC" 正则:r"$(\d+)$",
    切割后的字符串变成"AAAA ", " BBBB ", " CCCC" ,被匹配的片段 "$01$" 和 "$02$" 通过Match 对象返回.
    
    字符串片段和Match 对象被混合起来作为列表返回,每个列表元素是一个二元组,前者是匹配位置前的字符串片段,后者是Match 对象.
    上面的例子的返回形式为:
    
    [
         ("AAAA ", Match("$01$")),
         (" BBBB ", Match("$02$")),
         (" CCCC", None)
    ]
    
    最后一个片段后面没有匹配,所以Match 对象用None 代替
    
    Parameters
    ----------
    pattern : Union[str, re.Pattern]
        正则表达式,可以是字符串或编译后的Pattern 对象.
    text : str
        原字符串.

    Returns
    -------
    result_list : List[Tuple[str, Optional[re.Match]]]
        返回值是一个列表,其中每个元组包含两个元素,前者是匹配前的字符串片段,后者是Match 对象.

    '''
    m_iter = pattern.finditer(text) if isinstance(pattern, re.Pattern) else re.finditer(pattern, text)
    result_list = []
    last_stop = 0
    for m in m_iter:
        start, stop = m.span()
        s = text[last_stop: start]
        last_stop = stop
        result_list.append((s, m))
    
    result_list.append((text[last_stop:], None))
    return result_list

注释里说的应该够清楚了。

使用效果

要处理的字符串是:

s = r"V_{CM}=V_{S} / 2,V_{OUT}=V_{S} / 2,V_{S}=V_{+} - V_{-} =5V,V_{+} =2.5V,V_{-} = -2.5V"

用来匹配记号的正则是:

sub_pattern = r"_\{(.+?)\}"
p = re.compile(sub_pattern)  # 可能编译后正则匹配会更快吧

函数调用:

text_find_and_split(p, s) # 第一个参数可以是字符串sub_pattern,也可以是编译后的p

切割结果:

lm = [('V', <re.Match object; span=(1, 6), match='_{CM}'>),
 ('=V', <re.Match object; span=(8, 12), match='_{S}'>),
 (' / 2,V', <re.Match object; span=(18, 24), match='_{OUT}'>),
 ('=V', <re.Match object; span=(26, 30), match='_{S}'>),
 (' / 2,V', <re.Match object; span=(36, 40), match='_{S}'>),
 ('=V', <re.Match object; span=(42, 46), match='_{+}'>),
 (' - V', <re.Match object; span=(50, 54), match='_{-}'>),
 (' =5V,V', <re.Match object; span=(60, 64), match='_{+}'>),
 (' =2.5V,V', <re.Match object; span=(72, 76), match='_{-}'>),
 (' = -2.5V', None)]

然后再做一些小处理,就可以把原字符串插入到word 里面,并且自动添加上下标格式:

for i in lm:
    s, m = i
    s_run = cp0.add_run(s)
    s_run.font.name = "Times New Roman"
    if m is None:
        break
    gs = m.groups()
    assert len(gs) == 1
    sub_text = gs[0]
    sub_run = cp0.add_run(sub_text)
    sub_run.font.name = "Times New Roman"
    sub_run.font.subscript = True

效果如下图:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值