使用正则表达式在Python中匹配并替换多行字符串

5
我需要帮助匹配两个字符串并用空字符串进行替换。由于我还是 Python 和编程的新手,所以非常感谢您的帮助:
crypto pki certificate chain TP-self-signed-1357590403
  +30820330 30820218 A0030201 02020101 300D0609 2A864886 F70D0101 05050030
  +31312F30 2D060355 04031326 494F532D 53656C66 2D536967 6E65642D 43657274
  +69666963 6174652D 31333537 35393034 3033301E 170D3139 30313234 31353436
  +34345A17 0D323030 31303130 30303030 305A3031 312F302D 06035504 03132649
  +4F532D53 656C662D 5369676E 65642D43 65727469 66696361 74652D31 33353735
  +39303430 33308201 22300D06 092A8648 86F70D01 01010500 0382010F 00308201
  +0A028201 0100E69D C133454E 401E763A 7686E453 5D58020D 0E6E122F A0F19E15
  +E0975148 666110BD C1F09B86 CB701C20 EF85E024 F759A921 D11DA10C A13BA3BD
  +20006387 917287CE EA0CFDDC 2FA5DD07 E5B200F4 108CACA1 DCEF0E4E EEE908ED
  +2ACD693B FC90A24F 9F865CB9 859FEFB0 EB8904D4 8FA83D29 E93B892F 32F3EC7D
  +EAA2850E 1793BBCE 86EA47B2 15645634 D81EA89C 1C2BC092 766DF58F 0B289A82
  +0C92E551 7AA9588E F5B41A41 6DB4C785 101E674D BBBCFB42 9F4F9A25 70389515
  +D1C07E2F 18C0557D 95283E90 3CCD2966 5EBF5668 A6B0B847 0B278906 E5BFA668
  +EFBE938A BE70C4C0 1A8D7218 71463EA5 49540A45 DF307B4C 459E657D C039BB68
  +F047B0B2 2F250203 010001A3 53305130 0F060355 1D130101 FF040530 030101FF
  +301F0603 551D2304 18301680 141FADF3 CC2C2293 810EDAA8 9E55327C D2B7D88A
  +88301D06 03551D0E 04160414 1FADF3CC 2C229381 0EDAA89E 55327CD2 B7D88A88
  +300D0609 2A864886 F70D0101 05050003 82010100 91E63F44 376F91C1 C50C08E4
  +B29B902B B1BC7831 C5607897 030835A6 108FC1F2 6F3DEE23 EF3E8FFF 81A121B5
  +26596004 F8F61DFD 1B603C5D 42D850E6 439C7CAE BFC285AE 3FD83870 125594C0
  +51EAAC09 BF42446F C6399B90 D0E10ACA B208819B 645BECE5 DBDDA9AD EBA1FCD9
  +2B14D0DE AB2AC1BF FF064076 ADBB4540 17AB77A4 C6B0DA3B 1BC0F5B8 44030E7B
  +27318CEE 14C90739 DD8684A8 9346EEC1 3F4958EF 835BA822 F58523C9 E9F83105
  +D3E68700 20DAFC5E B1B8CF5B BAC5CEB3 00321088 43125173 51FC8006 270731E6
  +0E0C6183 68BABA99 BD9F4F28 1EDA82D4 F00F1359 F30B6501 BC468C89 49111AB2
  +CBDE5A9D DB8DB33A 45FE6C96 7D49A70F 4C299618

将始终有27行,以第一行开头

第二行是:

crypto pki certificate chain TP-self-signed-1357590403
 -certificate self-signed 01 nvram:IOS-Self-Sig#1.cer

1
对于输入的字符串,您期望得到什么输出字符串?您想要抹掉整个东西吗? - Allan
是的,我只想删除这部分。 - Ivan Madolev
检查一下我的答案!它应该可以工作;-) - Allan
4个回答

2
如果您想匹配包括下一行的文本,可以匹配所有行,并使用负向先行断言来确定下一行不以crypto开头。然后匹配一个换行符和crypto直到行末:
然后匹配一个换行符和crypto直到行末:
^crypto pki certificate chain TP-self-signed-.*(?:\n(?!crypto).*)*\ncrypto.*

正则表达式演示

如果起始行应与结束行相同,则可以使用捕获组和反向引用来匹配第一行:

最初的回答:如果要求起始行和结束行相同,可以使用带有反向引用的捕获组来匹配第一行。

^(crypto pki certificate chain TP-self-signed-.*)(?:\n(?!\1).*)*\n\1

最初的回答:
你的代码可能会像这样:

正则表达式演示

您的代码可能看起来像

pattern = r'^(crypto pki certificate chain TP-self-signed-.*)(?:\n(?!\1).*)*\n\1'
df=re.sub(pattern, '' , file, 0, re.MULTILINE)

@WiktorStribiżew 你是对的,我已经更新了。谢谢,非常感谢! - The fourth bird
1
我不知道为什么它被踩了。这种展开循环的技术在正则表达式匹配性能方面是最好的。+1 绝对没问题。 - Wiktor Stribiżew
我已经尝试了,但仍然出现相同的问题。只有删除起始行:crypto pki certificate chain TP-self-signed-1357590403。 - Ivan Madolev
@IvanMadolev 那么你的内容是在一个文件中并且跨越多行吗?你能测试一下它是否包含Windows换行符吗?^crypto pki certificate chain TP-self-signed-.*(?:(?:\r?\n|\r)(?!crypto).*)*(?:\r?\n|\r)crypto.*或者多个换行符^crypto pki certificate chain TP-self-signed-.*(?:[\r\n]+(?!crypto).*)*[\r\n]+crypto.* - The fourth bird
1
正则表达式起作用了!谢谢。这是我代码中的一行。 - Ivan Madolev
显示剩余4条评论

1
为什么不直接使用这个正则表达式呢,保留HTML,不做解释。
(crypto pki certificate chain TP-self-signed-\d+)[\w\W]+?\1

并用空字符串删除它吗?

我是否漏掉了其他答案似乎在暗示涉及换行符的相对复杂的解决方案?

演示

编辑:根据您的评论“实际上我需要删除:crypto pki certificate chain TP-self-signed-1357590403以及以+开头的下26行”

您可以使用此正则表达式,该表达式选择紧随crypto pki certificate chain TP-self-signed-1357590403行之后以+开头的确切26行。

crypto pki certificate chain TP-self-signed-\d+(?:\n\s*\+[^\n]*){26}

演示

正如您在演示中所看到的那样,它确切地选择了以+开头的26行,并将其替换为空字符串。如果您遇到任何问题,请告诉我。


实际上我需要做的是删除:crypto pki certificate chain TP-self-signed-1357590403 还有下面 26 行以加号+开头的代码。 - Ivan Madolev
好的,现在有明确的事情要做。让我更新我的答案。 - Pushpesh Kumar Rajwanshi
1
可以了!谢谢!我现在会尝试调整我的脚本。 - Ivan Madolev
请问您如何使用pandas实现并将结果转换为csv文件?我的代码是: df=pd.read_csv(file, skiprows = 1, error_bad_lines=False).dropna() df=re.sub(r'crypto pki certificate chain TP-self-signed-\d+(?:\n\s+[^\n]){26}' , '' , file) df.to_csv(file, index=False)但是出现了以下错误: AttributeError: 'str' object has no attribute 'to_csv' - Ivan Madolev

1
您可以使用以下代码:

import re

inputStr = """crypto pki certificate chain TP-self-signed-1357590403
  +30820330 30820218 A0030201 02020101 300D0609 2A864886 F70D0101 05050030
  +31312F30 2D060355 04031326 494F532D 53656C66 2D536967 6E65642D 43657274
  +69666963 6174652D 31333537 35393034 3033301E 170D3139 30313234 31353436
  +34345A17 0D323030 31303130 30303030 305A3031 312F302D 06035504 03132649
  +4F532D53 656C662D 5369676E 65642D43 65727469 66696361 74652D31 33353735
  +39303430 33308201 22300D06 092A8648 86F70D01 01010500 0382010F 00308201
  +0A028201 0100E69D C133454E 401E763A 7686E453 5D58020D 0E6E122F A0F19E15
  +E0975148 666110BD C1F09B86 CB701C20 EF85E024 F759A921 D11DA10C A13BA3BD
  +20006387 917287CE EA0CFDDC 2FA5DD07 E5B200F4 108CACA1 DCEF0E4E EEE908ED
  +2ACD693B FC90A24F 9F865CB9 859FEFB0 EB8904D4 8FA83D29 E93B892F 32F3EC7D
  +EAA2850E 1793BBCE 86EA47B2 15645634 D81EA89C 1C2BC092 766DF58F 0B289A82
  +0C92E551 7AA9588E F5B41A41 6DB4C785 101E674D BBBCFB42 9F4F9A25 70389515
  +D1C07E2F 18C0557D 95283E90 3CCD2966 5EBF5668 A6B0B847 0B278906 E5BFA668
  +EFBE938A BE70C4C0 1A8D7218 71463EA5 49540A45 DF307B4C 459E657D C039BB68
  +F047B0B2 2F250203 010001A3 53305130 0F060355 1D130101 FF040530 030101FF
  +301F0603 551D2304 18301680 141FADF3 CC2C2293 810EDAA8 9E55327C D2B7D88A
  +88301D06 03551D0E 04160414 1FADF3CC 2C229381 0EDAA89E 55327CD2 B7D88A88
  +300D0609 2A864886 F70D0101 05050003 82010100 91E63F44 376F91C1 C50C08E4
  +B29B902B B1BC7831 C5607897 030835A6 108FC1F2 6F3DEE23 EF3E8FFF 81A121B5
  +26596004 F8F61DFD 1B603C5D 42D850E6 439C7CAE BFC285AE 3FD83870 125594C0
  +51EAAC09 BF42446F C6399B90 D0E10ACA B208819B 645BECE5 DBDDA9AD EBA1FCD9
  +2B14D0DE AB2AC1BF FF064076 ADBB4540 17AB77A4 C6B0DA3B 1BC0F5B8 44030E7B
  +27318CEE 14C90739 DD8684A8 9346EEC1 3F4958EF 835BA822 F58523C9 E9F83105
  +D3E68700 20DAFC5E B1B8CF5B BAC5CEB3 00321088 43125173 51FC8006 270731E6
  +0E0C6183 68BABA99 BD9F4F28 1EDA82D4 F00F1359 F30B6501 BC468C89 49111AB2
  +CBDE5A9D DB8DB33A 45FE6C96 7D49A70F 4C299618
crypto pki certificate chain TP-self-signed-1357590403"""

print(re.sub(r'crypto pki certificate chain TP-self-signed-\d+\s*[0-9a-fA-F+\s]+\s*crypto pki certificate chain TP-self-signed-\d+', '' , inputStr))

输出:

正则表达式演示: https://regex101.com/r/G9XciA/2/

正则表达式解释:

  • crypto pki certificate chain TP-self-signed-\d+\s* 匹配第一行,其中结尾仅考虑数字加上任何空格字符。
  • [0-9a-fA-F+\s]+将匹配十六进制字符、+和空格字符。
  • crypto pki certificate chain TP-self-signed-\d+\s* 最后一行到结束匹配。如果第一行和最后一行的ID相同,则匹配。

使用正则表达式:

crypto pki certificate chain TP-self-signed-(\d+)\s*[0-9a-fA-F+\s]+\s*crypto pki certificate chain TP-self-signed-\1

当你在正则表达式中使用第一个捕获组的反向引用时

示例: https://regex101.com/r/G9XciA/3


在Python shell上确实可以工作,但是当我尝试在我的代码中实现时,由于某些原因它不起作用。 - Ivan Madolev
1
@IvanMadolev:如果你把你的代码展示给我们,我们就可以帮助你解决这个问题! - Allan
1
你的正则表达式肯定是有效的!我知道出了什么问题,正在尝试自己修复。当我打开文件时,在应用正则表达式之前,我错误地删除了第一行!如果还有问题,我会发布代码。 - Ivan Madolev
实际上,Alan,我犯了一个错误...我需要匹配两个不同的字符串...中间可能会有一些行。如果您能看一下我编辑过的问题就好了。 - Ivan Madolev
代码
df=pd.read_csv(file, skiprows = 1, error_bad_lines=False).dropna()
df=re.sub(r'crypto pki certificate chain TP-self-signed-\d+(?:\n\s+[^\n]){26}' , '' , file)
df.to_csv(file, index=False)
出现错误:
AttributeError: 'str'对象没有'to_csv'属性
- Ivan Madolev
显示剩余2条评论

1

我无法确定您想要什么,因为您没有提供所需结果的信息,所以我们只能猜测。

如果您只是想全部替换,可以使用类似于以下内容的东西

from tkinter import *
import re

document_x = open('text.txt', encoding="utf8").read()

regex_test = re.sub(r".*\n*( +.*)*", "", document_x)

print(regex_test);

使用以下方法删除加密行之间的所有内容:

regex_test = re.sub(r"(?:\n(?!crypto).*)*", "" , document_x)

或者您可以使用以下方法删除加密行:
regex_test = re.sub("crypto pki certificate chain TP-self-signed-[0-9]+\n", "" , 
                     document_x, re.MULTILINE)

我已经在Python 3.6.1 shell中运行过以确认其可用。在线正则表达式测试工具虽然有帮助,但并不总是返回与Python本身相同的结果。
from tkinter import *
import re

document_x = open('text.csv', encoding="utf8").read()

regex_test = re.sub(r"(crypto[\s\S]*1357590403)", "", document_x)

print(regex_test);

您需要根据自己的需求进行修改,这只是一个示例。 假设您想要删除整个块,但不影响之前或之后的内容,例如:

Placeholder 1
crypto pki certificate chain TP-self-signed-1357590403
  +30820330 30820218 A0030201 02020101 300D0609 2A864886 F70D0101 05050030
  +31312F30 2D060355 04031326 494F532D 53656C66 2D536967 6E65642D 43657274
  +69666963 6174652D 31333537 35393034 3033301E 170D3139 30313234 31353436
  +34345A17 0D323030 31303130 30303030 305A3031 312F302D 06035504 03132649
  +4F532D53 656C662D 5369676E 65642D43 65727469 66696361 74652D31 33353735
  +39303430 33308201 22300D06 092A8648 86F70D01 01010500 0382010F 00308201
  +0A028201 0100E69D C133454E 401E763A 7686E453 5D58020D 0E6E122F A0F19E15
  +E0975148 666110BD C1F09B86 CB701C20 EF85E024 F759A921 D11DA10C A13BA3BD
  +20006387 917287CE EA0CFDDC 2FA5DD07 E5B200F4 108CACA1 DCEF0E4E EEE908ED
  +2ACD693B FC90A24F 9F865CB9 859FEFB0 EB8904D4 8FA83D29 E93B892F 32F3EC7D
  +EAA2850E 1793BBCE 86EA47B2 15645634 D81EA89C 1C2BC092 766DF58F 0B289A82
  +0C92E551 7AA9588E F5B41A41 6DB4C785 101E674D BBBCFB42 9F4F9A25 70389515
  +D1C07E2F 18C0557D 95283E90 3CCD2966 5EBF5668 A6B0B847 0B278906 E5BFA668
  +EFBE938A BE70C4C0 1A8D7218 71463EA5 49540A45 DF307B4C 459E657D C039BB68
  +F047B0B2 2F250203 010001A3 53305130 0F060355 1D130101 FF040530 030101FF
  +301F0603 551D2304 18301680 141FADF3 CC2C2293 810EDAA8 9E55327C D2B7D88A
  +88301D06 03551D0E 04160414 1FADF3CC 2C229381 0EDAA89E 55327CD2 B7D88A88
  +300D0609 2A864886 F70D0101 05050003 82010100 91E63F44 376F91C1 C50C08E4
  +B29B902B B1BC7831 C5607897 030835A6 108FC1F2 6F3DEE23 EF3E8FFF 81A121B5
  +26596004 F8F61DFD 1B603C5D 42D850E6 439C7CAE BFC285AE 3FD83870 125594C0
  +51EAAC09 BF42446F C6399B90 D0E10ACA B208819B 645BECE5 DBDDA9AD EBA1FCD9
  +2B14D0DE AB2AC1BF FF064076 ADBB4540 17AB77A4 C6B0DA3B 1BC0F5B8 44030E7B
  +27318CEE 14C90739 DD8684A8 9346EEC1 3F4958EF 835BA822 F58523C9 E9F83105
  +D3E68700 20DAFC5E B1B8CF5B BAC5CEB3 00321088 43125173 51FC8006 270731E6
  +0E0C6183 68BABA99 BD9F4F28 1EDA82D4 F00F1359 F30B6501 BC468C89 49111AB2
  +CBDE5A9D DB8DB33A 45FE6C96 7D49A70F 4C299618
crypto pki certificate chain TP-self-signed-1357590403
Placeholder 2

运行上面的示例,返回值将删除块,只留下周围的内容,即:
Placeholder 1

Placeholder 2

谢谢!实际上我正在尝试完全删除以 "crypto pki certificate chain TP-self-signed-1357590403" 开头和结尾的字符串。这两行上的数字始终相同。可以是txt或csv文件。 - Ivan Madolev
我更新了可能解决你所需的问题的代码,但它很可能需要一些修改才能完全符合你的要求,因为这只是一个粗略的示例。我这样做是因为我不确定你正在使用的源代码,在极特殊的情况下,如果发生冲突,你可能需要更改任意值。 - Twisted Fate
完美适用于txt文件。现在将尝试将其应用于csv,这是最初的要求! - Ivan Madolev
请记得选择一个答案来标记主题已解决,以免后续被强制关闭。我也尝试在电子表格(csv)上做了同样的事情,结果与txt文件相同,跨越30行,只保留光谱之外的2行。然而,由于我不知道你具体在做什么,你可能需要不同的方法。 - Twisted Fate
我现在正在尝试的事情很复杂,因为我正在运行一个脚本,该脚本记录到Cisco路由器以捕获配置中未保存的更改。因此,如果没有更改,则命令输出为空行,但现在它显示了我想要删除的那些行,但我现在又遇到了另一个问题,但我的正则表达式问题已得到解答,所以将其标记为已解决。 - Ivan Madolev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接