如何在Python字符串中插入字符字面量

3

我正在尝试在Python中编写正则表达式,其中一个涉及的字符是\001字符。将\001放入字符串中似乎不起作用。我还尝试过使用'string' + str(chr(1)),但正则表达式似乎无法捕获它。求求大家帮帮我,我已经为此苦苦挣扎了一整天。

import sys
import postgresql
import re

if len(sys.argv) != 2:
    print("usage: FixToDb <fix log file>")
else:
    f = open(sys.argv[1], 'r')
    timeExp = re.compile(r'(\d{2}):(\d{2}):(\d{2})\.(\d{6}) (\S)')
    tagExp = re.compile('(\\d+)=(\\S*)\001')
    for line in f:
        #parse the time
        m = timeExp.match(line)
        print(m.group(1) + ':' + m.group(2) + ':' + m.group(3) + '.' + m.group(4) + ' ' + m.group(5));
        tagPairs = re.findall('\\d+=\\S*\001', line)
        for t in tagPairs:
            tagPairMatch = tagExp.match(t)
            print ("tag = " + tagPairMatch.group(1) + ", value = " + tagPairMatch.group(2))

这是一个输入行的示例。我将'\001'字符替换为'~'以增加可读性。

15:32:36.357227 R 1 0 0 0 8=FIX.4.2~9=0067~35=A~52=20120713-19:32:36~34=1~49=PD~56=P~98=0~108=30~10=134

输出:

15:32:36.357227 R 标签 = 8,值 = FIX.4.29=006735=A52=20120713-19:32:3634=149=PD56=P98=0108=3010=134

因此,它不会在'\001'字符处停止。


1
你应该使用“原始”字符串来处理正则表达式... - Jon Clements
timeExp中,将整个时间表达式捕获在一组括号中是否更容易,这样您就不必重新构建时间表达式(print(m.group(1) + ':' ...)了吗? - Sam Mussmann
@Jon Clements: 我认为Alex没有使用原始字符串是因为他想在模式中包含字符串字面量。@Alex,如果你要避免使用原始字符串以便在模式中使用字符串字面量,则反斜杠应该加倍('\\')。 - Steven Rumbalski
@Sam Mussmann:好的,我计划将这些内容放入数据库中,并且需要拆分值以构建时间戳对象。 - Alex
请提供一个示例,展示你输入了什么,输出了什么,以及你希望得到什么样的输出。 - BrenBarn
显示剩余2条评论
3个回答

2

chr(1)应该可以使用,"\x01""\001"也可以。在你的示例中,看起来你同时使用了两个"\001"chr(1),所以除非你的数据中有两个相连的字符,否则这样做是行不通的。

你说正则表达式“似乎没有捕捉到它”,但你没有给出输入数据的示例,因此无法确定原因。

编辑:好吧,看起来问题与\001无关。这是经典的贪婪问题。你的tagExp表达式中的\S*将匹配一个\001字符(因为该字符不是空格)。因此,\S*将吞掉整行内容。使用\S*?使其变成非贪婪模式。

编辑:正如其他人指出的那样,你的反斜杠可能有问题。在正则表达式中,你会面临反斜杠加倍的问题:Python使用反斜杠进行自己的字符串转义(例如,\t表示制表符,\n表示换行符),但是正则表达式也使用反斜杠进行自己的用途(例如,\s表示空格)。通常的解决方案是使用原始字符串,但如果你想使用"\001"转义,则无法这样做。但是,你可以在timeExp正则表达式中使用原始字符串。然后在其他正则表达式中,将反斜杠加倍(除了\001,因为你希望它被解释为字符代码转义)。


抱歉,我不是想同时使用\001和str(chr(1)),那是在帖子中打错了。我还提供了一个示例,它都在一行中。 - Alex
@Alex:看看我的修改后的答案。问题与\001无关,而是因为\S*表达式的贪婪匹配在到达\001之前消耗了整行内容。 - BrenBarn
好的,我去掉了双反斜杠并在\S*后面加上'?',看起来工作得很好。非常感谢您,我非常感慨! - Alex

1

不应该使用\S来匹配可以是任何非空白字符(包括\001)的值,而应该使用[^\x01],它将匹配任何不是\001的字符。


0

@Sam Mussmann,不...

1(十进制)= \001(八进制)<> \x01(UNICODE)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接