Удалить всю строку в текстовом файле, который содержит с определенным словом / строкой в ​​Python - PullRequest
1 голос
/ 17 мая 2019

все. Я использую пример из SO и попытался удалить несколько строк / строк в текстовом файле, но не удалось. Строка строки, которую нужно удалить, например

             OSPF Process 1 with Router ID 1.1.1.1
                       Area: 0.0.0.11
               Link State Database  

Я смог удалить эту строку, указав точно всю строку / строку, как показано ниже, но это может удалить только одну строку за раз, и другая проблема заключается в том, что идентификатор маршрутизатора и области могут быть любым числом и динамически изменяться.

filename = 'raw.txt'
with open(filename, 'r') as fin:
    lines = fin.readlines()
with open('clean.txt', 'w') as fout:
    for line in lines:
        if 'Area: 0.0.0.10' not in line:
            fout.write(line)

Я пытался использовать startwith, но он не удаляется.

if not line.startswith('OSPF'):

Так выглядит и размещается строка в текстовом файле. OSPF ..., Area ..., Link ... строки не начинаются слева, они начинаются с пробела, поэтому я думаю, что поэтому с ним не работает.


     OSPF Process 1 with Router ID 1.1.1.1
                 Area: 0.0.0.11
         Link State Database 


some textxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

         OSPF Process 1 with Router ID 2.1.1.1
                 Area: 0.0.0.12
         Link State Database 

some textxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


     OSPF Process 1 with Router ID 2.2.2.2
                 Area: 0.0.0.33
         Link State Database 

some textxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Ожидается, как показано ниже после удаления этих строк

some textxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


some textxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


some textxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Пожалуйста, посоветуйте дальше и спасибо

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


     OSPF Process 1 with Router ID 1.1.1.1
                 Area: 0.0.0.11
         Link State Database 


например, выше 5 строк при выполнении скрипта .. он удалит 3 строки, но при этом останется 2 строки

другой пример

 * Link ID: 10.1.155.20
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 1
     Priority : Low
                         Area: 0.0.0.13
                 Link State Database


  Type      : Router
  Ls id     : 1.4.0.2
  Adv rtr   : 1.4.0.2

это имеет 4 строки (между областью и перед типом) ... при выполнении скрипта удалить только 2 строки ... и 2 останется .... Для этого ... финал должен быть как ниже

* Link ID: 10.1.155.20
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 1
     Priority : Low

  Type      : Router
  Ls id     : 1.4.0.2
  Adv rtr   : 1.4.0.2

Удалить конкретную строку и строку, а также следующую строку (после строки базы данных состояния связей)

clean.txt

**To remove this empty line
To remove this empty line
To remove this empty line**
  Type      : Router
  Ls id     : 1.4.0.1
  Adv rtr   : 1.4.0.1
  Ls age    : 996
  Len       : 48
  Options   :  ASBR  E
  seq#      : 8000002f
  chksum    : 0xe7f5
  Link count: 2
   * Link ID: 1.16.9.9
     Data   : 10.1.155.2
     Link Type: P-2-P
     Metric : 100
   * Link ID: 10.1.155.20
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 100
     Priority : Low

  Type      : Router
  Ls id     : 1.16.9.9
  Adv rtr   : 1.16.9.9
  Ls age    : 392
  Len       : 48
  Options   :  ABR  E
  seq#      : 8000001e
  chksum    : 0x3116
  Link count: 2
   * Link ID: 1.4.0.1
     Data   : 10.242.177.21
     Link Type: P-2-P
     Metric : 1
   * Link ID: 10.1.155.20
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 1
     Priority : Low
**To remove this empty line**

  Type      : Router
  Ls id     : 1.4.0.2
  Adv rtr   : 1.4.0.2
  Ls age    : 1194
  Len       : 96
  Options   :  ASBR  E
  seq#      : 8001cf7b
  chksum    : 0xbfae
  Link count: 6
   * Link ID: 1.4.0.2
     Data   : 255.255.255.255
     Link Type: StubNet
     Metric : 0
     Priority : Medium
   * Link ID: 1.4.0.1
     Data   : 10.0.0.2
     Link Type: P-2-P
     Metric : 10
   * Link ID: 10.0.0.0
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 10
     Priority : Low
   * Link ID: 10.40.8.0
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 100
     Priority : Low
   * Link ID: 19.23.23.15
     Data   : 10.40.10.130
     Link Type: P-2-P
     Metric : 10
   * Link ID: 1.4.10.200
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 10
     Priority : Low
To remove this empty line

  Type      : Router
  Ls id     : 100.100.0.10
  Adv rtr   : 100.100.0.10
  Ls age    : 171
  Len       : 84
  Options   :  ASBR  E
  seq#      : 8001a292
  chksum    : 0x5fa2
  Link count: 5
   * Link ID: 100.100.0.10
     Data   : 255.255.255.255
     Link Type: StubNet
     Metric : 12
     Priority : Medium
   * Link ID: 10.10.0.1
     Data   : 10.10.10.18
     Link Type: P-2-P
     Metric : 10
   * Link ID: 10.10.10.17
     Data   : 255.255.255.255
     Link Type: StubNet
     Metric : 10
     Priority : Medium
   * Link ID: 19.23.23.15
     Data   : 10.10.30.30
     Link Type: P-2-P
     Metric : 10
   * Link ID: 10.90.25.30
     Data   : 255.255.255.255
     Link Type: StubNet
     Metric : 10
     Priority : Medium

  Type      : Router
  Ls id     : 10.10.0.1
  Adv rtr   : 10.10.0.1
  Ls age    : 191
  Len       : 96
  Options   :  ASBR  E
  seq#      : 80013bcf
  chksum    : 0x9871
  Link count: 6
   * Link ID: 10.10.0.1
     Data   : 255.255.255.255
     Link Type: StubNet
     Metric : 12
     Priority : Medium
   * Link ID: 15.51.51.14
     Data   : 10.10.0.130
     Link Type: P-2-P
     Metric : 10
   * Link ID: 10.10.0.129
     Data   : 255.255.255.255
     Link Type: StubNet
     Metric : 10
     Priority : Medium
   * Link ID: 100.100.0.10
     Data   : 10.10.10.17
     Link Type: P-2-P
     Metric : 10
   * Link ID: 10.10.10.18
     Data   : 255.255.255.255
     Link Type: StubNet
     Metric : 10
     Priority : Medium
   * Link ID: 16.16.16.0
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 10
     Priority : Low

  Type      : Router
  Ls id     : 15.51.51.14
  Adv rtr   : 15.51.51.14
  Ls age    : 2487
  Len       : 60
  Options   :  ASBR  ABR  E
  seq#      : 8000003c
  chksum    : 0x1714
  Link count: 3
   * Link ID: 10.242.95.12
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 1
     Priority : Low
   * Link ID: 10.10.0.1
     Data   : 10.10.0.129
     Link Type: P-2-P
     Metric : 1
   * Link ID: 10.10.0.128
     Data   : 255.255.255.252
     Link Type: StubNet
     Metric : 1
     Priority : Low
**To remove this empty line
To remove this empty line**

Ответы [ 3 ]

1 голос
/ 17 мая 2019

Вы можете использовать регулярное выражение, чтобы найти определенный текст и удалить его.Ниже приведен пример кода, вы можете играть с другим регулярным выражением в соответствии с вашими требованиями.

попробуйте ниже код:

import re
regex = "OSPF|Area|Link"
for line in lines:
    if not re.findall(regex, line):
        print line
1 голос
/ 17 мая 2019

Вместо того, чтобы читать построчно, вы могли бы читать все содержимое текстового файла и использовать шаблон для этого конкретного соответствия, принимая во внимание части цифр, которые могут различаться.

^[ \t]*OSPF Process \d+ with Router ID \d+(?:\.\d+){3}\s*Area: \d+(?:\.\d+){3}\s*Link State Database\s*(?:\n|$)

Пояснение

  • ^ Начало строки
  • [ \t]* Соответствие 0+ раз пробелу или табуляции
  • OSPF Process \d+ with Router ID \d+(?:\.\d+){3}Совпадение текста с учетом формата цифр \d+ для идентификатора процесса и маршрутизатора
  • \s*Area: \d+(?:\.\d+){3} Совпадение Area:, за которым следуют 1+ цифр и 3 раза повторение точки и 1+ цифр
  • \s*Link State Database Соответствует 0+ раз символу пробела и буквенному тексту
  • \s*(?:\n|$) Соответствует 0+ раз символу пробела и затем соответствует либо новой строке, либо утверждению конца строки

Regex demo | Python demo

Например:

import re

filename = 'raw.txt'
pattern = r"^[ \t]*OSPF Process \d+ with Router ID \d+(?:\.\d+){3}\s*Area: \d+(?:\.\d+){3}\s*Link State Database\s*(?:\n|$)"
with open(filename, 'r') as fin:
    res = re.sub(pattern, "", fin.read(), 0, re.MULTILINE)
    text_file = open("clean.txt", "w")
    text_file.write(res)
    text_file.close()

Редактировать

Чтобы сопоставить пустой символ новой строки после, вы можете использовать команду addпосле базы данных:

  • [ \t]* Соответствие 0+ раз пробелу или строке
  • (?: Группа без захвата
    • (?:\r?\n|\r)[ \t]* Соответствие новой строки с последующим соответствием0+ раз табуляция или пробел
  • )? Закрыть группу без захвата и сделать ее необязательной
  • $ Утвердить конец строки

Полный шаблон:

^[ \t]*OSPF Process \d+ with Router ID \d+(?:\.\d+){3}\s*Area: \d+(?:\.\d+){3}\s*Link State Database[ \t]*(?:(?:\r?\n|\r)[ \t]*)?$

Regex demo

1 голос
/ 17 мая 2019

Обратите внимание, что строка не начинается с OSPF, но с кучей пробелов и , затем OSPF. Попробуйте strip в первую очередь. Кроме того, startswith может принимать набор возможных префиксов, поэтому вы можете проверить все сразу.

for line in lines:
    if not line.strip().startswith(("OSPF", "Area", "Link State")):
        fout.write(line)

Обратите внимание, что это может не сработать, если некоторые строки в реальном тексте также начинаются с Area или аналогичного.

Вы также можете использовать регулярное выражение, чтобы строка имела для начала с нескольких пробелов, а затем одно из этих ключевых слов:

import re
for line in lines:
    if not re.match(r"\s+(Area|OSPF|Link State)", line):
        fout.write(line)
...