使用python拆分带分隔符的字符串,同时忽略引号内的分隔符和转义引号

时间:2011-03-01 04:15:20

标签: python regex delimiter

我试图根据分隔符的位置拆分字符串(我试图从Fortran代码中删除注释)。我可以使用以下字符串中的!进行拆分:

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

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

,则会失败
z = '''print "h\"i!" ! Remove me'''

可以修改正则表达式来处理转义引号吗?或者我甚至不应该使用正则表达式来解决这类问题?

3 个答案:

答案 0 :(得分: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合作,我在过去一小时左右发现的每一篇参考文献似乎都描述了一种完全不同的语言。 MEH!

答案 1 :(得分: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'''(?:[^!"']|((?<!\\)"|(\\\\)+").*?((?<!\\)"|(\\\\)+")|((?<!\\)'|(\\\\)+').*?((?<!\\)"|(\\\\)+'))+'''

这有点难看。 。

答案 2 :(得分: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解析器。根据许可限制,您可以重新编写代码来可靠地解析“代码而不是注释”。