2014-11-21 77 views
0

我想用Python中的正則表達式替換給定的模式,使用re。這是我寫的Python代碼:Python正則表達式:替換忽略空字符串

import re 

fname = './prec.f90' 
f = open(fname) 
lines = f.readlines() 
f.close() 
for i, line in enumerate(lines): 
    search = re.findall('([\d*]?\.[\d*]?)+?[^dq\_]', line) 
    if search != []: 
     print('Real found in line #%d: ' %i) 
     print search 
     print('The following line:\n %s' %line) 
     print('will be replace by:') 
     newline = re.sub('([\d*]?\.[\d*]?)+?[^dq\_]', r'\g<1>d0\g<2>', line) 
     print('%s' %newline) 

而且prec.f90包含類似的東西(這只是一個例子,它並不意味着所有我想要替換字符串格式爲[x]_[yz] = ...;):

x_pr = 0.1; y_pr = 0.2; z_pr = 0.1q0 
    x_sp = 0.1; y_sp = 0.1d0; z_sp = 0.1q0 
    x_dp = 0.1; y_dp = 0.1d0; z_dp = 0.1q0 
    x_qp = .1; y_qp = 0.1d0; z_qp = 0.1q0 
    x_db = 0.; y_db = 0.1d0; y_db = 0.1q0 

我的目標是要修改所有的格式,如:0.1.10.,要達到這樣的0.1d0;我不想修改其他模式。問題是re.findall('[\d*]?\.[\d*]?)+?([^dq\_]')與我正在查找的模式匹配,但也爲其他的返回空字符串。因此,當我運行這段代碼時,它失敗了,無法替換空字符串re.sub()中的第一組和第二組。

我想一種解決方案是忽略re.sub中的空字符串,或者在其中有類似條件的參數,但我無法弄清楚。

任何幫助,將不勝感激!

+0

由於您使用'*'選擇了所有組件,因此它[失去空字符串]是失敗的。你想要替換的行的最小字符串是多少?如果它是'.x',則將第二個'\ d *'改爲'\ d +' – beroe 2014-11-21 18:58:12

+0

問題是它們可以具有我提到的3種形式:'x.y','.y'和'x.'。我想(需要)涵蓋所有這些情況。 – MBR 2014-11-23 10:47:42

回答

0

我終於想出了這樣一段代碼,如預期運作:

import re 

fname = './prec.f90' 
f = open(fname) 
lines = f.readlines() 
f.close() 
# If there was no end of the line character (\n) we would need to check if 
# this is the end of the line (something like ([^dq\_0-9]|$) 
regex = re.compile(r'(\d*\.\d*)([^dq\_0-9])') 
for i, line in enumerate(lines): 
    search = regex.findall(line) 
    if search != []: 
     print('Real found in line #%d: ' %i) 
     print search 
     print('The following line:\n %s' %line) 
     print('will be replace by:') 
     newline = regex.sub(r'\g<1>d0\g<2>', line) 
     print('%s' %newline) 

我第一次與更復雜的正則表達式([\d*]?\.[\d*]?)+?[^dq\_]上來,因爲別的我總是匹配以d,q_結尾的任何字符串的第一部分。這似乎是因爲\d*不夠貪心;在「忽略」集中添加0-9解決問題。

0

可以簡化sub作爲

>>> str="x_db = 0.; y_db = 0.1d0; y_db = 0.1q" 
>>> re.sub(r'(0\.1|\.1|0\.)(?=;)', r'\g<1>0d0', str) 
'x_db = 0.0d0; y_db = 0.1d0; y_db = 0.1q' 

正則表達式(0\.1|\.1|0\.)(?=;)將匹配0.1.10.其次爲;

+0

請閱讀我的編輯,我想要替換的字符串有一個更一般的形式,這只是一個例子。 – MBR 2014-11-21 18:38:46

0
(x_[a-zA-Z]{2}\s*=)\s+[^;]+ 

嘗試this.Replace通過\1 0.1d0。看到演示。

http://regex101.com/r/qZ6sE3/2

import re 
p = re.compile(ur'(x_[a-zA-Z]{2}\s*=)\s+[^;]+') 
test_str = u"x_pr = 0.1; y_pr = 0.2; z_pr = 0.1q0\nx_sp = 0.1; y_sp = 0.1d0; z_sp = 0.1q0\nx_dp = 0.1; y_dp = 0.1d0; z_dp = 0.1q0\nx_qp = .1; y_qp = 0.1d0; z_qp = 0.1q0\nx_db = 0.; y_db = 0.1d0; y_db = 0.1q0" 
subst = u"\1 0.1d0" 

result = re.sub(p, subst, test_str) 
+0

我想要替換的字符串可以具有比'x_ [a-Z] = ...'更通用的形式。在我的問題是測試是什麼:一個簡單的測試:) – MBR 2014-11-23 10:48:57

+0

@MBR http://regex101.com/r/yP3iB0/6 ?????? – vks 2014-11-23 12:08:26

+0

不,因爲我不想只修改「0.1」但實際上是任何實數,並且我沒有將所有表達式都以半列結尾。我想用它的值替換原來的字符串,而不是一個虛擬的'0.1'。 – MBR 2014-11-23 17:06:35