扫描textfile查找有两个has numb的字符串

2024-10-02 00:35:28 发布

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

我想打开一个文本文件,扫描以RECORD-FEB开头的行。如果一行以RECORD-FEB开头,我想找到两个大写字母,后跟一个数字(称为number1),后跟一个文字$--,然后是另一个数字(称为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

Tags: researchmaindefline数字filenamerecord
1条回答
网友
1楼 · 发布于 2024-10-02 00:35:28

基本正则表达式问题

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

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

方括号不表示文字字符串。他们建立了一个字符类,这意味着括号中的任何字符都可以匹配字符串中的相应字符。具体来说,[ ]并不意味着字面双破折号。它的意思是“任何字符,要么是破折号或破折号”,这是多余的,而不是你想要的

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

捕捉数字

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

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

编译正则表达式

现在,您正在循环的每个迭代中使用^{}。这将从头开始为文件中的每一行编译regex。对于小文件来说没什么大不了的,但是您会注意到大文件的区别

一般来说,如果您发现自己多次应用正则表达式,请考虑使用^{}预编译它。然后可以对已编译的^{}对象使用^{}方法,该方法的操作方式相同,但速度要快得多

行号

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

for num, line in enumerate(file):
    ...

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

将元素放在行的前面

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

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

代码

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

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被追加到列表matches中,该列表打印在末尾

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

import shutil

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

相关问题 更多 >

    热门问题