Python正则表达式:替换忽略空字符串

时间:2014-11-21 11:00:21

标签: python regex

我正在尝试使用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中的空字符串,或者在其中包含类似条件的参数,但我无法弄清楚如何。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分: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.,后跟;

答案 1 :(得分:0)

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

试试这个。\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)

答案 2 :(得分: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\_],因为我始终匹配以dq_结尾的任何字符串的第一部分。这似乎是因为\d*不够贪心;在“忽略”集中添加0-9可以解决问题。