Python 扫描文本文件查找包含两个has编号的字符串

Python 扫描文本文件查找包含两个has编号的字符串,python,Python,我想打开一个文本文件,扫描以RECORD-FEB开头的行。如果一行以RECORD-FEB开头,我想找到两个大写字母,后跟一个数字(称为number1),后跟一个literal$-,然后是另一个数字(称为number2)。如果number1等于number2,那么我想在该行的开头添加一个“@”符号并返回行号,否则继续 匹配行中的示例模式: AB566$--12 Invalid case RT21$--9 Invalid Case TP667$--677 Valid case 我的问题是

我想打开一个文本文件,扫描以
RECORD-FEB
开头的行。如果一行以
RECORD-FEB
开头,我想找到两个大写字母,后跟一个数字(称为number1),后跟一个literal
$-
,然后是另一个数字(称为number2)。如果number1等于number2,那么我想在该行的开头添加一个“@”符号并返回行号,否则继续

匹配行中的示例模式:

AB566$--12  Invalid case 
RT21$--9    Invalid Case
TP667$--677 Valid case
我的问题是
re.search
不起作用:它既没有给出结果也没有给出错误。基本上,我的
abc
功能不起作用

import re
def main():
    with open(r"filename.txt") as f:
        for line in f:
            if "RECORD-FEB" in line:
            #   print(line)
                abc(line)

def abc(line):
    case = re.search(r"\[A-Z]{2}\d+\[$][--]\d+",line)
    if case:
        print(line)
        # code to append @ at beginning of that line and return line number
main()
filename.txt的内容如下:

    abcd efg avcd AB566$--12 pqrs
 RECORD-FEB    MB566$--12 abcd efgh lmno
       RECORD-FEB    FREWREWRE EWRRWERE AB566$--12 EREWWRRW
import re

def main():
    pattern = re.compile(r"[A-Z]{2}(\d+)\$--(\d+)")
    matches = []
    with open(r"filename.txt") as f, open(r"filename.txt.out", "w") as out:
        for num, line in enumerate(f):
            if line.strip().startswith("RECORD-FEB"):
                case = pattern.search(line)
                if case and case.group(1) == case.group(2):
                    matches.append(num)
                    line = '@' + line
            print(line, file=out)
    print(matches)

main()

基本正则表达式发行

代码中最大的问题是在正则表达式中不必要地使用反斜杠和方括号。除此之外,你基本上是在正确地解决你的问题

反斜杠通常使特殊字符成为文字,并赋予常规字符特殊含义。无论何时执行
\[
,您都在与文本开头括号进行匹配,这在您的特定应用程序中是不希望执行的

方括号不表示文字字符串。它们设置了一个字符类,这意味着括号中的任何字符都可以与字符串中的相应字符相匹配。具体而言,
[-]
并不表示文字双破折号。它表示“任何破折号或破折号字符”,这是多余的,不是你想要的

您需要将
r“\[A-Z]{2}\d+[$][-]\d+”
更改为更简单的
r“[A-Z]{2}\d+\$-\d+”
。您唯一需要的字符类是大写字母的
[A-Z]
。您唯一需要的转义特殊字符是
\$
,以获得文字美元符号,而不是EOL的匹配项

捕捉数字

为了能够比较这些数字,您需要捕获部分匹配项。您可以使用括号来标记捕获组。现在您的正则表达式看起来像
r“[A-Z]{2}(\d+)\$-(\d+)”

您不需要转换数字的文本表示形式。如果字符串不匹配,则它们不匹配

编译正则表达式

现在,您正在循环的每个迭代中使用。这将从头开始为文件中的每一行编译正则表达式。对于小文件来说,这不是什么大问题,但是您会注意到大文件的不同

一般来说,如果你发现自己不止一次地应用正则表达式,可以考虑预先编译它。然后你可以在编译的对象上使用这个方法,它以相同的方式运行,但是要快得多。 行号

要在迭代文件时获取行号,请将文件迭代器包装到:

您可以将行号传递给
abc
,如果存在匹配项,将返回行号,或者更好的是,您可以完全消除
abc

将元素前置到一行

通常,就地修改文件是不实际的。文件是磁盘上字节的集合。如果要将
@
字符插入文件中的随机位置,则必须将所有剩余字节移位。相反,您通常会写入另一个文件,除要写入的行外,所有行都相同更改。如果希望插入看起来无缝,则可以在插入后移动生成的文件以覆盖原始文件

这意味着您必须打开一个输出文件。与您的模式匹配的每一行都使用
@
前缀写入。所有其他行都将按原样传递

代码

综合以上所有因素,您可以得到如下结果:

    abcd efg avcd AB566$--12 pqrs
 RECORD-FEB    MB566$--12 abcd efgh lmno
       RECORD-FEB    FREWREWRE EWRRWERE AB566$--12 EREWWRRW
import re

def main():
    pattern = re.compile(r"[A-Z]{2}(\d+)\$--(\d+)")
    matches = []
    with open(r"filename.txt") as f, open(r"filename.txt.out", "w") as out:
        for num, line in enumerate(f):
            if line.strip().startswith("RECORD-FEB"):
                case = pattern.search(line)
                if case and case.group(1) == case.group(2):
                    matches.append(num)
                    line = '@' + line
            print(line, file=out)
    print(matches)

main()
我已经放弃了
abc
函数,因为它没有太多功能。所有匹配的行号,其中
number1==number2
都会被追加到列表
匹配的
,并在最后打印出来

如果要在完成后覆盖原始文件,请执行以下操作:

import shutil

...
    shutil.move("filename.txt.out", "filename.txt")

那么问题出在哪里呢?看起来你要么没有写完你的问题,要么你希望我们读懂你的想法。请添加相关的示例输入文本。你得到了什么输出与你期望的输出相比?出了什么问题?你得到了错误吗?如果是,请发布它,最好是带有堆栈跟踪。我已经添加了信息,对此表示歉意他说它工作正常。如果行中有“RECORD-FEB”,则没有一行满足