如何在python中将文本格式与字符串匹配而不使用正则表达式?

时间:2011-04-14 19:55:27

标签: python regex matlab readfile

我正在阅读一个文件行,其格式为

[ 0 ] L= 9 (D) R= 14 (D) p= 0.0347222 e= 10 n= 34

我看到Matlab code要阅读

给出的这个文件
[I,L,Ls,R,Rs,p,e,n] = textread(f1,'[ %u ] L= %u%s R= %u%s p= %n e=%u n=%u')

我想用Python阅读这个文件。我唯一知道的是正则表达式,阅读这一行的一部分会导致类似

re.compile('\s*\[\s*(?P<id>\d+)\s*\]\s*L\s*=\s*(?P<Lint>\d+)\s*\((?P<Ltype>[DG])\)\s*R\s*=\s*(?P<Rint>\d+)\s*')

这太丑了!在Python中有更简单的方法吗?

4 个答案:

答案 0 :(得分:3)

通过使用escape / replace ...

构建regexp,可以使regexp更具可读性
number = "([-+0-9.DdEe ]+)"
unit = r"\(([^)]+)\)"
t = "[X] L=XU R=XU p=X e=X n=X"
m = re.compile(re.escape(t).replace("X", number).replace("U", unit))

答案 1 :(得分:2)

这对我来说或多或少是pythonic:

line = "[ 0 ] L= 9 (D) R= 14 (D) p= 0.0347222 e= 10 n= 34"

parts = (None, int, None,
         None, int, str,
         None, int, str,
         None, float,
         None, int,
         None, int)

[I,L,Ls,R,Rs,p,e,n] = [f(x) for f, x in zip(parts, line.split()) if f is not None]

print [I,L,Ls,R,Rs,p,e,n]

答案 2 :(得分:1)

Python没有scanf等效as stated on the re page for Python

  

Python目前没有与scanf()等价的东西。正则表达式通常比scanf()格式字符串更强大,但也更冗长。下表提供了scanf()格式标记和正则表达式之间的一些或多或少的等效映射。

但是,您可以使用该页面上的映射构建自己的类似scanf的模块。

答案 3 :(得分:1)

Pyparsing是不可读和脆弱的正则表达式处理器的后备。下面的解析器示例处理您声明的格式,以及任何类型的额外空格和赋值表达式的任意顺序。就像在正则表达式中使用命名组一样,pyparsing支持结果名称,因此您可以使用dict或属性语法(data ['Lint']或data.Lint)访问已解析的数据。

from pyparsing import Suppress, Word, nums, oneOf, Regex, ZeroOrMore, Optional

# define basic punctuation
EQ,LPAR,RPAR,LBRACK,RBRACK = map(Suppress,"=()[]")

# numeric values
integer = Word(nums).setParseAction(lambda t : int(t[0]))
real = Regex(r"[+-]?\d+\.\d*").setParseAction(lambda t : float(t[0]))

# id and assignment fields
idRef = LBRACK + integer("id") + RBRACK
typesep = LPAR + oneOf("D G") + RPAR
lExpr = 'L' + EQ + integer("Lint")
rExpr = 'R' + EQ + integer("Rint")
pExpr = 'p' + EQ + real("pFloat")
eExpr = 'e' + EQ + integer("Eint")
nExpr = 'n' + EQ + integer("Nint")

# accept assignments in any order, with or without leading (D) or (G)
assignment = lExpr | rExpr | pExpr | eExpr | nExpr
line = idRef + lExpr + ZeroOrMore(Optional(typesep) + assignment)


# test the parser
text = "[ 0 ] L= 9 (D) R= 14 (D) p= 0.0347222 e= 10 n= 34"
data = line.parseString(text)
print data.dump()


# prints
# [0, 'L', 9, 'D', 'R', 14, 'D', 'p', 0.034722200000000002, 'e', 10, 'n', 34]
# - Eint: 10
# - Lint: 9
# - Nint: 34
# - Rint: 14
# - id: 0
# - pFloat: 0.0347222

此外,解析操作在分析时执行string-&gt; int或string-&gt; float转换,以便之后值已经是可用的形式。 (在pyparsing中的思考是,在解析这些表达式时,你知道由数字组成的单词 - 或Word(nums) - 将安全地转换为int,那么为什么不立即进行转换,而不仅仅是获取返回匹配字符串并且必须重新处理字符串序列,尝试检测哪些是整数,浮点数等?)