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

使用python拆分带分隔符的字符串,同时忽略引号内的分隔符和转义引号,python,regex,delimiter,Python,Regex,Delimiter,我试图根据分隔符的位置拆分字符串(我试图从Fortran代码中删除注释)。我可以使用进行拆分: x = '''print "hi!" ! Remove me''' pattern = '''(?:[^!"]|"[^"]*")+''' y = re.search(pattern, x) 但是,如果字符串包含转义引号,则此操作失败,例如 z = '''print "h\"i!" ! Remove me''' 可以修改正则表达式来处理转义引号吗?或者我甚至不应该使用regexp来解决这类问题吗?您

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

x = '''print "hi!" ! Remove me'''
pattern = '''(?:[^!"]|"[^"]*")+'''
y = re.search(pattern, x)
但是,如果字符串包含转义引号,则此操作失败,例如

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

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

您需要的是一个否定的lookback断言:
(?)

例如:

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

print(y.group(0))


正如在评论中指出的,上面的表达式不会处理转义反斜杠。它也不会处理FORTRAN中允许的单引号。这个表达式也适用于这些情况(我认为):


pattern=r''(?:[^!“])|((?Fortran解析实际上相当棘手(参见例如线程)。我非常不熟悉语法的细节,也不知道“!”可能出现在哪里。因此,我有一个想法:注释本身包含“!”的可能性有多大?如果不太可能,您可以简单地删除每行最后一个“!”之后的所有内容:

def cleanup(line):
  splitlist = line.split("!")
  if len(splitlist) > 1 and "\"" not in splitlist[-1]:
      return '!'.join(splitlist[:-1]).strip()
  else:
      return line
这并不完美,但在最坏的情况下,您最终会留下一些部分注释。这永远不会影响实际代码

编辑:

看起来NumPy在中包含了一个基于python的Fortran解析器。根据许可限制,您可以重新编写该解析器,以可靠地解析“代码而不是注释”。

下面是一个经验证的正则表达式(from),用于匹配可能包含反斜杠转义引号的双引号字符串文本:

r'"[^"\\]*(?:\\.[^"\\]*)*"'
在分隔引号中,它使用以反斜杠开头的任何一对字符,而不必费心识别第二个字符;这使它能够处理转义反斜杠和其他转义序列,而不需要额外的麻烦。它还可以在没有和的情况下尽可能地高效,而Python不支持和

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

r'^((?:[^!"]+|"[^"\\]*(?:\\.[^"\\]*)*")*)!.*$'
这只匹配包含注释的行,并捕获组#1中注释之前的所有内容。对于以
开头的行,捕获长度可能为零。此正则表达式用于
而不是
搜索
,如下所示:

import re

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

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


免责声明:此答案与FORTRAN无关,只与遵循问题中指定规则的代码有关。我从未使用过FORTRAN,在过去一个小时左右我找到的每个参考资料似乎都描述了一种完全不同的语言。Meh!

转义反斜杠怎么办?这将处理转义反斜杠:
模式=r''(?:[^!]|)(?)?
r'^((?:[^!"]+|"[^"\\]*(?:\\.[^"\\]*)*")*)!.*$'
import re

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

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