【问题标题】:Regular expression to match both csv fields正则表达式匹配两个 csv 字段
【发布时间】:2014-10-16 21:58:16
【问题描述】:

我的数据看起来像这样(注意 SPX 之后的 PM):

11 Dec 1650.00 (SPXPM1130L1650-E),1.90,0.0,1.35,2.30,0,10,11 Dec 1650.00 (SPXPM1130X1650-E),0.0,0.0,376.20,380.00,0,0,

或像这样(注意没有 -E、W 或 PM):

14 Oct 800.00 (SPX1418J800),0.0,0.0,1067.10,1071.40,0,0,14 Oct 800.00 (SPX1418V800),0.09,0.0,0.0,0.05,0,25,

或看起来像这样的数据(注意 SPX 后面的额外 W):

11 Jan 1075.00 (SPXW1128A1075-E),0.0,0.0,215.30,217.00,0,0,11 Jan 1075.00 (SPXW1128M1075-E),0.05,-0.10,0.05,0.10,10,15535,

我在 Python 中使用以下正则表达式来获取数据的整个第一个逗号分隔字段(即"14 Oct 800.00 (SPX1418J800)"):

spx_symbol = re.compile("\\(SPX(1[0-9])([0-9]{2})([A-Z])([0-9]{3,4})-E\\)")

这适用于上面的第二种数据格式(具有 W 的那个),但是当有 NOT 额外的“W”和一些没有当我尝试从固定位置获取令牌时,额外的 -E 或 PM,。请参阅下面的函数

当我输入上面的第一行时,我得到:

spx_symbol.split(line)

这是split 之后的这些标记的使用方式,并且有时只有原始正则表达式有效:

def ExpiryMonth(s):
    """
    SPX contract months
    """
    call_months = "ABCDEFGHIJKL"
    put_months = "MNOPQRSTUVWX"

    try:
        m = call_months.index(s)
    except ValueError:
        m = put_months.index(s)

    return m

#spx_symbol = re.compile("\\(SPX(1[0-9])([0-9]{2})([A-Z])([0-9]{3,4})-E\\)") WORKS SOME OF TIME
spx_symbol = re.compile("\((SPX(1[0-9])([0-9]{2})([A-Z])([0-9]{3,4})(-E)?\\))")

def parseSPX(s):
    """
    Parse an SPX quote string, return expiry date and strike
    """
    tokens = spx_symbol.split(s)

    if len(tokens) == 1:
        return {'dtExpiry': None, 'strike': -1}

    year = 2000 + int(tokens[1])
    day = int(tokens[2])
    month = ExpiryMonth(tokens[3])
    strike = float(tokens[4])

    dtExpiry = datetime.date(year, month, day)

    return ({'dtExpiry': dtExpiry, 'strike': strike})

【问题讨论】:

  • 您是否使用正则表达式来解析 csv 文件?如果是这样,你为什么不使用 csv 模块呢?如果不是,为什么这些是 csv 文件中的字段很重要?你在这里实际上想做什么?
  • 你到底想从这些行中得到什么数据?
  • @AirThomas,根据这个问题,我假设他只需要第一个字段的一部分来回答它。如果您需要的不仅仅是 Ivan,我还建议您查看 csv 模块
  • @ivan,你为什么认为你需要一个正则表达式?您的文件由逗号分隔,您想要第一个逗号之前的数据,所以正如我在回答中向您展示的那样,只需使用普通拆分或 csv 模块
  • This blog post 应该在发布正则表达式问题之前阅读。

标签: python regex csv


【解决方案1】:

我在 python 中有一个像这样的正则表达式,它试图获取数据的整个第一个逗号分隔字段。换句话说,例如“14 Oct 800.00 (SPX1418J800)”

只需使用split,以逗号分隔并获取第一个元素,您不需要重新:

s="14 Oct 800.00 (SPX1418J800),0.0,0.0,1067.10,1071.40,0,0,14 Oct 800.00 (SPX1418V800),0.09,0.0,0.0,0.05,0,25"

print(s.split(",",1)[0])
14 Oct 800.00 (SPX1418J800)


s1 = "11 Jan 1075.00 (SPXW1128A1075-E),0.0,0.0,215.30,217.00,0,0,11 Jan 1075.00 (SPXW1128M1075-E),0.05,-0.10,0.05,0.10,10,15535,"
print(s1.split(",",1)[0])
11 Jan 1075.00 (SPXW1128A1075-E)

如果您只想要括号内的内容,根据您问题中的输出,您可以再次拆分:

s = "14 Oct 800.00 (SPX1418J800),0.0,0.0,1067.10,1071.40,0,0,14 Oct 800.00 (SPX1418V800),0.09,0.0,0.0,0.05,0,25"

print(s.split(",",1)[0].rsplit(" ",1)[-1])
(SPX1418J800)

或者干脆使用 csv 模块:

import  csv
with open(my.csv) as f:
    reader = csv.reader(f,delimiter=",")
    for line in reader:
        print(line[0])
14 Oct 800.00 (SPX1418J800)
11 Jan 1075.00 (SPXW1128A1075-E)

【讨论】:

  • 查看原帖中添加的文字。我需要调用 parseSPX 并提取罢工和到期,而不仅仅是第一个字段的内容。不清楚是我的错。对不起。
  • 您能否添加您期望的输出,因为仍然不清楚您期望什么
【解决方案2】:

这是我使用的正则表达式:

"\((SPXW?(1[0-9])([0-9]{2})([A-Z])([0-9]{3,4})(-E)?\))"

您可以在这里看到它的功能。我正在打印整个匹配的部分

>>> first_fields = [
... "14 Oct 800.00 (SPX1418J800)",
... "11 Jan 1075.00 (SPXW1128A1075-E)"
... ]
>>> spx_symbols = re.compile("\((SPXW?(1[0-9])([0-9]{2})([A-Z])([0-9]{3,4})(-E)?\))")
>>> for f in first_fields:
...     print spx_symbols.search(f).group(0)
...
(SPX1418J800)
(SPXW1128A1075-E)

我所做的更改:

W? - This looks for an optional "W"
(-E)? - This looks for an optional "-E"

【讨论】:

  • 我尝试了您的新正则表达式,但它不起作用。但是,我没有一个完整的问题,所以你回答正确,但不是我的最终问题。查看修改后的帖子。
猜你喜欢
  • 2021-09-02
  • 2014-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 2022-12-07
相关资源
最近更新 更多