我想打开一个文本文件,扫描以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
基本正则表达式问题
代码中最大的问题是在正则表达式中不必要地使用反斜杠和方括号。除此之外,你基本上是在正确地解决你的问题
反斜杠通常使特殊字符成为文字,并赋予常规字符特殊的含义。任何时候进行
\[
,都是在匹配文本的左括号,这在您的特定应用程序中是不希望的方括号不表示文字字符串。他们建立了一个字符类,这意味着括号中的任何字符都可以匹配字符串中的相应字符。具体来说,
[ ]
并不意味着字面双破折号。它的意思是“任何字符,要么是破折号或破折号”,这是多余的,而不是你想要的您需要将
r"\[A-Z]{2}\d+[$][ ]\d+"
更改为更简单的r"[A-Z]{2}\d+\$ \d+"
。唯一需要的字符类是[A-Z]
用于大写字母。唯一需要的转义特殊字符是\$
,以获得一个文字美元符号,而不是EOL的匹配捕捉数字
为了能够比较这些数字,你需要捕捉比赛的一部分。您可以使用括号来标记捕获组。现在您的正则表达式看起来像
r"[A-Z]{2}(\d+)\$ (\d+)"
您不需要转换数字的文本表示形式。如果字符串不匹配,它们就不匹配
编译正则表达式
现在,您正在循环的每个迭代中使用^{} 。这将从头开始为文件中的每一行编译regex。对于小文件来说没什么大不了的,但是您会注意到大文件的区别
一般来说,如果您发现自己多次应用正则表达式,请考虑使用^{} 预编译它。然后可以对已编译的^{} 对象使用^{} 方法,该方法的操作方式相同,但速度要快得多
行号
要在迭代文件时获取行号,请将文件迭代器包装到^{} :
您可以将行号传递给
abc
,如果有匹配项则返回,或者更好的是,您可以完全消除abc
将元素放在行的前面
通常,就地修改文件是不实际的。文件是磁盘上字节的集合。如果要将
@
字符插入文件中的随机位置,则必须将剩余的所有字节移位。相反,您通常会写入另一个文件,除要更改的行外,所有行都是相同的。如果希望插入看起来天衣无缝,可以在插入后移动生成的文件以覆盖原始文件这意味着您必须打开一个输出文件。与您的模式匹配的每一行都用
@
前缀写入。所有其他线路将按原样通过代码
综合以上所有因素,可以得到如下结果:
我已经去掉了
abc
函数,因为它做的不多。所有匹配行号,其中number1 == number2
被追加到列表matches
中,该列表打印在末尾如果要在完成后覆盖原始文件,请执行以下操作:
相关问题 更多 >
编程相关推荐