正则表达式 - 总长度有最大值但组可以变量,不包括句点

时间:2018-05-09 01:33:31

标签: python regex

我正在regexThomson Reuters RIC代码撰写Python。权益一具有以下规则:

regex_ric_equity = re.compile(r'''(
^([A-Z0-9]+)          # root symbol, at least 1 character, not lower case
([a-z]*)              # brokerage, lower case letter(s), optional
(\.[A-Za-z]+)$        # delimiter ("."), and exchange code like "N" for NYSE
)''', re.VERBOSE)

现在这很有效。这是一个问题。整个RIC的总长度最多为7个字符,但周期不算。第一组和第三组至少需要1,第二组是可选的,但它们必须全部<= 7。无法弄清楚如何做到这一点。

我尝试用括号围绕整个事情并执行{2,7},但这不起作用,因为它包含句点,所以它看起来至少匹配2个句点。

regex_ric_equity = re.compile(r'''(
(
^([A-Z0-9]+)          # root symbol, at least 1 character, not lower case
([a-z]*)              # brokerage, lower case letter(s), optional
(\.[A-Za-z]+)$        # delimiter ("."), and exchange code like "N" for NYSE
){2,7}                # max 7 characters, at least 1 root and brokerage
)''', re.VERBOSE)

有什么想法吗?感谢。

编辑:我从他们作为汤森路透客户的文档获得了股票的RIC规则,而不是来自维基百科页面。以下是相关语言:

  

股票<​​/强>

     

股票是一个通用术语,用于涵盖相关工具类型,如普通股,普通股,优先股和其他相关股票类型。   权益RIC有几个组成部分:Equity RIC根为大写,经纪人字符为小写(如果适用),最后为交换标识符。

     
      
  • EQUITY ROOT
  •   
  • 经纪人字符(如果需要)
  •   
  • 定界符(。)
  •   
  • 交换标识符
  •   
     

代码标识特定发行人,可能最多七个字母或数字。字母词根应该是有意义的,并且如果可能的话,与发布组织有关,作为助记符,例如,XON for Exxon Corp.没有要求root在全球范围内是唯一的,因此不需要为同一个根分配发行者所有市场。对于不同的发行人,根可以在不同的市场中重复使用;但是,在一个国家内,根本不会重复。子公司应该与母公司有不同的根源。

     

报价和交换楼层报价

     

获取交易所或楼层显示的完整报价的RIC如下:

     

权益根示例

     

示例格式:VOLVb.ST

     
      
  • VOLV for Volvo
  •   
  • 经纪人字符(如果需要)
  •   
  • 定界符(。)
  •   
  • Exchange标识符,例如ST for Stockholm Exchange
  •   
     

日本上市证券

     

日本上市证券的结构如下:

     

权益根示例

     

示例格式:6501.T

     
      
  • 日立普通股的SICC代码6501
  •   
  • 分隔符(。)
  •   
  • 交换标识符,例如东京证券交易所的T
  •   

3 个答案:

答案 0 :(得分:1)

由于总长度可能因模式本身中的字符而不同,因此根据定义,它变为不规则模式,因此超出了正则表达式的范围。

你可能用复杂的反向引用和预测来编造一个复杂的模式但是利用正则表达式引擎的特性可能会比仅仅对你的匹配进行后处理以查看它们是否与允许的总数相匹配更慢(更不用说可读性)了RIC长度,如:

RIC_PATTERN = re.compile(r"^([A-Z]+)([a-z]*)\.?([A-Za-z]+)$")

def get_ric(source):
    ric = RIC_PATTERN.search(source)
    if ric and sum(len(r) for r in ric.groups()) < 8:
        return ric.groups()  # or return the match itself if you need more info

并测试它:

print(get_ric("RIC.SE"))     # ('RIC', '', 'SE')
print(get_ric("RICab.SE"))   # ('RIC', 'ab', 'SE')
print(get_ric("R.N"))        # ('R', '', 'N')
print(get_ric("RIClong.SE")) # None
print(get_ric("bad.RIC"))    # None
print(get_ric("RIC..BAD"))   # None

话虽如此,正如wp78de建议的那样,RIC定义(至少是维基百科上的定义)不是你想要在这里匹配的。

答案 1 :(得分:0)

以编程方式检查长度限制是理想的。

但是,使用Nested Conditional Regex,我们可以按如下方式提出RIC正则表达式(请注意,这可能是维护噩梦):

Demo

正则表达式:

^([A-Z0-9])?                                                                                                                # first character is [A-Z0-9] (capture group 1)
(?(1)                                                                                                                       # if capture group 1 is set
    \.[A-Za-z]{1,6} |                                                                                                       # then check if there is min 1 and max 6 chars after the dot (total 7, including dot 8)
    ([A-Z0-9]{2})?                                                                                                          # else check first 2 characters are [A-Z0-9] (capture group 2)
    (?(2)                                                                                                                   # if capture group 2 is set
        \.[A-Za-z]{1,5} |                                                                                                   # then check if there is min 1 and max 5 chars after the dot (total 7, including dot 8)
        ([A-Z0-9]{3})?
        (?(3)
            \.[A-Za-z]{1,4} |
            ([A-Z0-9]{4})?
            (?(4)
                \.[A-Za-z]{1,3} |
                ([A-Z0-9]{5})?
                (?(5)
                    \.[A-Za-z]{1,2} |
                    ([A-Z0-9]{6})?                                                                                          # else check first 6 characters are [A-Z0-9] (capture group 6)
                    (?(6)                                                                                                   # if capture group 6 is set
                        \.[A-Za-z] |                                                                                        # then check if there is 1 char after the dot (total 7, including dot 8)
                        ([A-Z0-9][a-z])?
                        (?(7)
                            \.[A-Za-z]{1,5} |
                            ([A-Z0-9][a-z]{2})?
                            (?(8)
                                \.[A-Za-z]{1,4} |
                                ([A-Z0-9][a-z]{3})?
                                (?(9)
                                    \.[A-Za-z]{1,3} |
                                    ([A-Z0-9][a-z]{4})?
                                    (?(10)
                                        \.[A-Za-z]{1,2} |
                                        ([A-Z0-9][a-z]{5})?
                                        (?(11)
                                            \.[A-Za-z] |
                                            ([A-Z0-9]{2}[a-z])?
                                            (?(12)
                                                \.[A-Za-z]{1,4} |
                                                ([A-Z0-9]{2}[a-z]{2})?
                                                (?(13)
                                                    \.[A-Za-z]{1,3} |
                                                    ([A-Z0-9]{2}[a-z]{3})?
                                                    (?(14)
                                                        \.[A-Za-z]{1,2} |
                                                        ([A-Z0-9]{2}[a-z]{4})?
                                                        (?(15)
                                                            \.[A-Za-z] |
                                                            ([A-Z0-9]{3}[a-z])?
                                                            (?(16)
                                                                \.[A-Za-z]{1,3} |
                                                                ([A-Z0-9]{3}[a-z]{2})?
                                                                (?(17)
                                                                    \.[A-Za-z]{1,2} |
                                                                    ([A-Z0-9]{3}[a-z]{3})?
                                                                    (?(18)
                                                                        \.[A-Za-z] |
                                                                        ([A-Z0-9]{4}[a-z])?
                                                                        (?(19)
                                                                            \.[A-Za-z]{1,2} |
                                                                            ([A-Z0-9]{4}[a-z]{2})?
                                                                            (?(20)
                                                                                \.[A-Za-z]  |
                                                                                ([A-Z0-9]{5}[a-z])?
                                                                                (?(21)
                                                                                    \.[A-Za-z]
                                                                                ) 
                                                                            ) 
                                                                        )
                                                                    ) 
                                                                ) 
                                                            )
                                                        ) 
                                                    ) 
                                                ) 
                                            )
                                        )
                                    )
                                )
                            )
                        )
                    )
                )
            )
        )
    )
)$

答案 2 :(得分:0)

引用链接维基百科页面:路透社仪器代码

  

对于股票,代码由RIC根组成(一到四   字符 - A到Z ),后跟一个句点符号然后是一个 - 或者   两个字符(A到Z)代码表示交换的   交易工具。每家公司都有一个独特的RIC   根。因此,国际商业机器的RIC Root将是   IBM无论在哪个国际商务交易所   机器被交易。 (突出显示已添加)。

因此,模式应如下所示:[A-Z]{1,4}\.[A-Z]{1,2}

那就是它。