2011-03-01 123 views
2

我想根据分隔符的位置(我试图从Fortran代码中删除注释)拆分字符串。我可以分割以下字符串使用!使用python分隔带分隔符的字符串,而忽略引号内的分隔符和转义引号

x = '''print "hi!" ! Remove me''' 
pattern = '''(?:[^!"]|"[^"]*")+''' 
y = re.search(pattern, x) 

但是,如果字符串包含转义引号失败,例如

z = '''print "h\"i!" ! Remove me''' 

修正正则表达式是否可以处理换码引号?或者我应该甚至没有使用正则表达式来解决这类问题?

回答

3

下面是可能包含反斜杠转义引号和双引号字符串字面匹配成熟的正则表达式(从Mastering Regular Expressions):

r'"[^"\\]*(?:\\.[^"\\]*)*"' 

在分界报价,它消耗任何对字符以反斜杠开始而不费心去识别第二个字符;这使得它可以处理逃脱的反斜杠和其他转义序列,而无需额外的麻烦。它的效率也可以在缺少possessive quantifiersatomic groups的情况下得到提高,这是Python不支持的。

您的应用程序的完整的正则表达式是:

r'^((?:[^!"]+|"[^"\\]*(?:\\.[^"\\]*)*")*)!.*$' 

这符合包含注释行,并捕获组#1中的注释前面的一切。对于开始!的行,捕获可以是零长度。这正则表达式是为使用与sub而非search,如下所示:

import re 

pattern = r'^((?:[^!"]+|"[^"\\]*(?:\\.[^"\\]*)*")*)!.*$' 

x = '''print "hi!" ! Remove me''' 
y = re.sub(pattern, r'\1', x) 
print(y) 

See it in action on ideone.com

免责声明:这个答案是不是FORTRAN,只有代码后面的问题中指定的规则。我从来没有与FORTRAN合作过,我在过去一小时左右发现的所有参考文献似乎都描述了一种完全不同的语言。咩!

2

你需要的是一个消极的后向断言:(?<!...)

例如:

z = r'''print "h\"i!" ! Remove me''' 
pattern = r'''(?:[^!"]|(?<!\\)".*(?<!\\)")+''' 
y = re.search(pattern, z) 

print(y.group(0)) 


输出:

print "h\"i!" 



如在评论中指出,上面的表达式不会处理转义反斜杠。它也不会处理FORTRAN允许的单引号。这应该对这些情况以及工作(我认为):

pattern = r'''(?:[^!"']|((?<!\\)"|(\\\\)+").*?((?<!\\)"|(\\\\)+")|((?<!\\)'|(\\\\)+').*?((?<!\\)"|(\\\\)+'))+''' 

这是开始有点难看。 。 。

+0

逃脱反斜杠怎么样? – 2011-03-01 05:47:40

+0

这将处理转义反斜杠:'pattern = r'''(?:[^!“] |((?<!\\)”|(\\\\)+“)。*?((?< !\\)“|(\\\\)+”))+''''但是FORTRAN允许使用单引号(')和双引号(“),这根本不处理。总体而言,使用正则表达式来做这个可能不是最好的解决方案。 – amicitas 2011-03-01 06:11:27

2

Fortran解析实际上非常棘手(请参阅线程here)。我非常不熟悉语法的细节,并且'!'可能会发生。所以这里有一个想法:评论本身有多大可能包括'!' ?如果不太可能,您可以在最后一个'!'之后删除所有内容。在每行中:

def cleanup(line): 
    splitlist = line.split("!") 
    if len(splitlist) > 1 and "\"" not in splitlist[-1]: 
     return '!'.join(splitlist[:-1]).strip() 
    else: 
     return line 

这并不完美,但最糟糕的是,您最终会留下部分评论。这不应该影响实际的代码。

编辑:

看起来NumPy的包括在F2py package一个基于Python的Fortran解析器。根据许可限制,您可能会重新做到这一点,以便可靠地解析“代码而不是评论”。

相关问题