确定一行是否有python中未结束的括号或引号

2024-09-25 06:26:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在寻找一个简单的方法打开一个文件,并搜索每一行,看看是否有未结束的帕伦斯和引号。如果该行有未结束的parens/quotes,我希望将该行打印到文件中。我知道我可以用一堆难看的if/for语句来完成它,但是我知道python对于re-module(我对此一无所知)或其他一些东西可能有更好的方法,但是我对这种语言还不太了解。在

谢谢!在

编辑:一些示例行。如果你把它复制到记事本或其他地方,并关闭自动换行(有些行可能很长),那么阅读起来会更容易。此外,文件中有超过100K的行,所以效率太好了!在

SL  ID=0X14429A0B TY=STANDARD OWN=0X429A03 EXT=22 SLTK=0X1C429A0B MP=0X684003F0 SUB=0X24400007
RT  ID=0X18429A19 TY=CALONSC OWN=0X14429A0B EXLP=0X14429A0C CMDS=(N:0X8429A04,C:0X14429A0B) SGCC=2 REL=1 DESC="AURANT YD-INDSTRY LD" ATIS=T
RT  ID=0X18429A1A TY=CALONSC OWN=0X14429A0B EXLP=0X14429A08 CMDS=(R:0X8429A04,N:0X8429A05,C:0X14429A0B) SGCC=2 REL=2 DESC="AURANT YD TO TRK.1" ATIS=T
RT  ID=0X18429A1B TY=CALONSC OWN=0X14429A0B EXLP=0X14429A0A CMDS=(R:0X8429A04,R:0X8429A05,C:0X14429A0B) SGCC=2 REL=3 DESC="AURANT YD TO TRK.2" ATIS=T
SL  ID=0X14429A0C TY=STANDARD OWN=0X429A03 EXT=24 SLTK=0X1C429A0B MP=0X684003F1 SUB=0X24400007
RT  ID=0X18429A1C TY=CALONSC OWN=0X14429A0C EXLP=0X14429A0B CMDS=(N:0X8429A04,C:0X14429A0C) SGCC=2 REL=1 DESC="AURANT YD-INDSTRY LD" ATIS=T
TK  ID=0X1C429A08 TY=BLKTK OWN=0X429A03 EXT=12 LRMP=0X6C40BDAF LEN=5837 FSPD=60 PSPD=65 QUAL=TRK.1 MAXGE=0 MAXGW=0 JAL=4 ALT=12 SUB=0X24400007 RULES=(CTC:B:UP:0X24400007:485.7305:486.8359:T) LLON=-118.1766772 RLON=-118.1620059 LLAT=34.06838375 RLAT=34.07811764 LELE=416.6983 RELE=425.0596 ULAD=NO URAD=NO
PT  ID=0X20429A0F TY=STANDARD OWN=0X1C429A08 LTK=0X1C40006C RTK=0X1C429A0C REL=1 LEN=1 LQUAL="TRK.1" RQUAL="TRK.1"
PTK OWN=0X1C429A08 PID=0X1C429A13

Tags: 文件iddescstandardrelrtcmdsown
3条回答

使用解析器包似乎有些过火,但它非常快:

text = """\
SL  ID=0X14429A0B TY=STANDARD OWN=0X429A03 EXT=22 SLTK=0X1C429A0B MP=0X684003F0 SUB=0X24400007
RT  ID=0X18429A19 TY=CALONSC OWN=0X14429A0B EXLP=0X14429A0C CMDS=(N:0X8429A04,C:0X14429A0B) SGCC=2 REL=1 DESC="AURANT YD-INDSTRY LD" ATIS=T
RT  ID=0X18429A1A TY=CALONSC OWN=0X14429A0B EXLP=0X14429A08 CMDS=(R:0X8429A04,N:0X8429A05,C:0X14429A0B) SGCC=2 REL=2 DESC="AURANT YD TO TRK.1" ATIS=T
RT  ID=0X18429A1B TY=CALONSC OWN=0X14429A0B EXLP=0X14429A0A CMDS=(R:0X8429A04,R:0X8429A05,C:0X14429A0B) SGCC=2 REL=3 DESC="AURANT YD TO TRK.2" ATIS=T
SL  ID=0X14429A0C TY=STANDARD OWN=0X429A03 EXT=24 SLTK=0X1C429A0B MP=0X684003F1 SUB=0X24400007
RT  ID=0X18429A1C TY=CALONSC OWN=0X14429A0C EXLP=0X14429A0B CMDS=(N:0X8429A04,C:0X14429A0C) SGCC=2 REL=1 DESC="AURANT YD-INDSTRY LD" ATIS=T
TK  ID=0X1C429A08 TY=BLKTK OWN=0X429A03 EXT=12 LRMP=0X6C40BDAF LEN=5837 FSPD=60 PSPD=65 QUAL=TRK.1 MAXGE=0 MAXGW=0 JAL=4 ALT=12 SUB=0X24400007 RULES=(CTC:B:UP:0X24400007:485.7305:486.8359:T) LLON=-118.1766772 RLON=-118.1620059 LLAT=34.06838375 RLAT=34.07811764 LELE=416.6983 RELE=425.0596 ULAD=NO URAD=NO
PT  ID=0X20429A0F TY=STANDARD OWN=0X1C429A08 LTK=0X1C40006C RTK=0X1C429A0C REL=1 LEN=1 LQUAL="TRK.1" RQUAL="TRK.1"
PTK OWN=0X1C429A08 PID=0X1C429A13 GOOD
PTK OWN=0X1C429A(08 PID=0X1C429A13 BAD
PTK OWN=0X1C429A08 )PID=0X1C429A13 BAD
PTK OWN=0X1C(42(9A))08 PID=0X1C429A13 GOOD
PTK OWN=0X1C(42(9A))08 PID=0X1C42(9A13 BAD
PTK OWN=0X1C(42(9A))08 PID=0X1C42"("9A13 GOOD
"""

from pyparsing import nestedExpr, quotedString

paired_exprs = nestedExpr('(',')')  |  quotedString

for i, line in enumerate(text.splitlines(), start=1):
    # use pyparsing expression to strip out properly nested quotes/parentheses
    stripped_line = paired_exprs.suppress().transformString(line)

    # if there are any quotes or parentheses left, they were not 
    # properly nested
    if any(unwanted in stripped_line for unwanted in '()"\''):
        print i, ':', line

印刷品:

^{pr2}$

如果您不认为会有向后不匹配的parens(即“)”),您可以这样做:

with open("myFile.txt","r") as readfile, open("outFile.txt","w") as outfile:
    for line in readfile:
        if line.count("(") != line.count(")") or line.count('"') % 2 != 0:
            outfile.write(line)

否则,您将不得不一次计算一个,以检查不匹配,如下所示:

^{pr2}$

我想不出比这更好的办法了。Python不支持递归正则表达式,因此正则表达式的解决方案是正确的。在

关于这一点还有一点:考虑到您的数据,最好将其放入函数中并拆分字符串,这很容易用正则表达式来实现,如下所示:

import re
splitre = re.compile(".*?=(.*?)(?:(?=\s*?\S*?=)|(?=\s*$))")
with open("myFile.txt","r") as readfile, open("outFile.txt","w") as outfile:
    for line in readfile:
        def matchParens(text):
            count = 0
            for char in text:
                if char == ")":
                    count -= 1
                elif char == "(":
                    count += 1
                if count < 0:
                    break
            return count != 0 or text.count('"') % 2 != 0
        if any(matchParens(text) for text in splitre.findall(line)):
            outfile.write(line)

这样做可能更好的原因是它单独检查每个值对,这样,如果在一个值对中有一个开放paren,在后面的一个值对中有一个闭paren,它就不会认为没有不平衡paren。在

  1. 只需从一行中提取所有有趣的符号。在
  2. 当您得到一个 结束符号。在
  3. 如果堆栈是干净的,则符号是平衡的。如果 堆栈下溢或没有完全展开,你有不平衡的线。在

下面是检查行的示例代码-我在第一行中插入了一个括号。在

d = """SL  ID=0X14429A0B TY=STANDARD OWN=0X429A(03 EXT=22 SLTK=0X1C429A0B MP=0X684003F0 SUB=0X24400007
RT  ID=0X18429A19 TY=CALONSC OWN=0X14429A0B EXLP=0X14429A0C CMDS=(N:0X8429A04,C:0X14429A0B) SGCC=2 REL=1 DESC="AURANT YD-INDSTRY LD" ATIS=T
RT  ID=0X18429A1A TY=CALONSC OWN=0X14429A0B EXLP=0X14429A08 CMDS=(R:0X8429A04,N:0X8429A05,C:0X14429A0B) SGCC=2 REL=2 DESC="AURANT YD TO TRK.1" ATIS=T
RT  ID=0X18429A1B TY=CALONSC OWN=0X14429A0B EXLP=0X14429A0A CMDS=(R:0X8429A04,R:0X8429A05,C:0X14429A0B) SGCC=2 REL=3 DESC="AURANT YD TO TRK.2" ATIS=T
SL  ID=0X14429A0C TY=STANDARD OWN=0X429A03 EXT=24 SLTK=0X1C429A0B MP=0X684003F1 SUB=0X24400007
RT  ID=0X18429A1C TY=CALONSC OWN=0X14429A0C EXLP=0X14429A0B CMDS=(N:0X8429A04,C:0X14429A0C) SGCC=2 REL=1 DESC="AURANT YD-INDSTRY LD" ATIS=T
TK  ID=0X1C429A08 TY=BLKTK OWN=0X429A03 EXT=12 LRMP=0X6C40BDAF LEN=5837 FSPD=60 PSPD=65 QUAL=TRK.1 MAXGE=0 MAXGW=0 JAL=4 ALT=12 SUB=0X24400007 RULES=(CTC:B:UP:0X24400007:485.7305:486.8359:T) LLON=-118.1766772 RLON=-118.1620059 LLAT=34.06838375 RLAT=34.07811764 LELE=416.6983 RELE=425.0596 ULAD=NO URAD=NO
PT  ID=0X20429A0F TY=STANDARD OWN=0X1C429A08 LTK=0X1C40006C RTK=0X1C429A0C REL=1 LEN=1 LQUAL="TRK.1" RQUAL="TRK.1"
PTK OWN=0X1C429A08 PID=0X1C429A13"""

def unbalanced(line):
    close_symbols = {'"' : '"', '(': ")", '[': ']', "'" : "'"}
    syms = [x for x in line if x in '\'"[]()']
    stack = []
    for s in syms:
        try:
            if len(stack) > 0 and s == close_symbols[stack[-1]]:
                stack.pop()
            else:
                stack.append(s)
        except: # catches stack underflow or closing symbol lookup
            return True
    return len(stack) != 0


print unbalanced("hello 'there' () []")
print unbalanced("hello 'there\"' () []")
print unbalanced("][")

lines = d.splitlines()  # in your case you can do open("file.txt").readlines()

print [line for line in lines if unbalanced(line)]

对于大文件,您不希望将所有文件读入内存,因此请使用如下片段:

^{pr2}$

相关问题 更多 >