2011-04-14 46 views
4

我讀入文件列舉的形式線用如何在python中將文本格式與沒有正則表達式的字符串匹配?

[ 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中做到這一點?

+1

試試這個:https://hkn.eecs.berkeley.edu/~dyoo/python/scanf/ – 2011-04-14 19:57:20

+1

其實,關於你的正則表達式唯一不好的地方就是它不是用詳細模式寫的(有很多評論)。使用一個名爲捕獲組的每行擴展它就會變成一個_beautiful_,(而且準確,高效,可維護且功能齊全)! – ridgerunner 2011-04-15 00:59:19

+0

問題是正則表達式必然會對某些輸入做一些不希望的事情,特別是當有奇怪的字符時,並且沒有明確的標準。我只想要我知道的東西會有用。 – sudo 2017-11-28 19:50:26

回答

1

Pyparsing是不可讀回退和脆弱的正則表達式處理器。下面的解析器示例處理您聲明的格式,以及各種額外的空格,以及賦值表達式的任意順序。就像您在regex中使用命名組一樣,pyparsing支持結果名稱,以便您可以使用字典或屬性語法(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 

另外,解析動作做與字符串> int或與字符串>浮充轉換在分析時,使以後的值已經在可用的形式。 (pyparsing中的思想是,在解析這些表達式時,您知道一個由數字組成的單詞 - 或Word(nums) - 將安全地轉換爲int,所以爲什麼不直接進行轉換,而不是僅返回匹配的字符串和不得不重新處理字符串序列,試圖檢測哪些是整數,浮點數等?)

1

Python沒有scanf等價物as stated on the re page for Python

Python目前沒有等效於scanf()。正則表達式通常比scanf()格式的字符串更強大,但也更加冗長。下表提供了一些或多或少的scanf()格式標記和正則表達式之間的等價映射。

但是,您可以使用該頁面上的映射構建自己的scanf模塊。

3

您可以通過逃逸構建它/替換正則表達式更具可讀性...

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)) 
+0

'%u'應該被替換爲'\ d +'和** not **'([ - + 0-9.DdEe] +)'和'%s'可以替換爲'\ S +'參見[模擬scanf ](http://docs.python.org/library/re.html#simulating-scanf) – jfs 2011-04-15 12:58:17

2

這看上去或多或少Python的對我說:

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] 
相關問題