delete line after previous line match

Viewed 79

This might be very straightforward but I am having bit of trouble while deleting unwanted line in my text file:

subject name="Biology" value="12th"
topic name="system" value="anything"
topic
subject name="mathematics" value="12th"
topic name="system" value="anything"
other topics ="anything" value="anything"
topic
subject name="chem102" value="12th"
topic name="system" value="anything"
topic
subject name="ComputerSc" value="12th"
topic name="system" value="anything"
other topics ="anything" value="anything"
topic

I want to remove topic line from specific clade by matching subject name from list:

list=['Biology','chem102']

desired output:

subject name="Biology" value="12th"
topic name="system" value="anything"

subject name="mathematics" value="12th"
topic name="system" value="anything" 
other topics ="anything" value="anything"
topic

subject name="chem102" value="12th"
topic name="system" value="anything"

subject name="ComputerSc" value="12th"
topic name="system" value="anything"
other topics ="anything" value="anything"
topic

Here's what I am trying

import re

IO=open('fileout.txt','w') 
IF=open('filein.txt','r') 

for line in IF.readlines():
    if re.search('subject name="[^\s]+"',line):
        for i in list:
            if re.search('subject name="{list[i]}"',line):
                line=line.replace("topic","")
                IO.write(line)

sorry if this question is already answered. Thank you!

3 Answers

I think you can add a bit of programming logic here to check each line that starts with subject. If it does, check the name value, and if it is in the list, mark the optional line to be removed, and once you come to that line, skip writing the line into the output file and reset the flag.

See a Python demo:

import re

l=['Biology','chem102']
remove_topic = False

with open('fileout.txt','w') as IO:
    with open('filein.txt','r') as IF:
        for line in IF:
            if line.startswith("subject"):
                name = re.search(r'\bname="([^"]*)"', line)
                if name:
                    if name.group(1) in l:
                        remove_topic = True
                IO.write(line)
            elif line.strip() == "topic" and remove_topic:
                IO.write("\n")
                remove_topic = False
            else:
                IO.write(line)

I don't know about the Python code but if you join your list into a giant regex boolean then you can do this:

regex

(subject name=\"(?:Biology|chem102)\"[\s\S]+?)\r?\n^topic$|(^topic$\r?\n)

replacement

\1\2\n

https://regex101.com/r/ccpwKQ/1/

Another regex solution can be

^(subject\s+name="(?:Biology|chem102)".*(?:\n(?!subject\s|topic$).*)*\n)topic

See regex proof.

EXPLANATION

--------------------------------------------------------------------------------
  ^                        the beginning of the string
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    subject                  'subject'
--------------------------------------------------------------------------------
    \s+                      whitespace (\n, \r, \t, \f, and " ") (1
                             or more times (matching the most amount
                             possible))
--------------------------------------------------------------------------------
    name="                   'name="'
--------------------------------------------------------------------------------
    (?:                      group, but do not capture:
--------------------------------------------------------------------------------
      Biology                  'Biology'
--------------------------------------------------------------------------------
     |                        OR
--------------------------------------------------------------------------------
      chem102                  'chem102'
--------------------------------------------------------------------------------
    )                        end of grouping
--------------------------------------------------------------------------------
    "                        '"'
--------------------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
    (?:                      group, but do not capture (0 or more
                             times (matching the most amount
                             possible)):
--------------------------------------------------------------------------------
      \n                       '\n' (newline)
--------------------------------------------------------------------------------
      (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
        subject                  'subject'
--------------------------------------------------------------------------------
        \s                       whitespace (\n, \r, \t, \f, and " ")
--------------------------------------------------------------------------------
       |                        OR
--------------------------------------------------------------------------------
        topic                    'topic'
--------------------------------------------------------------------------------
        $                        before an optional \n, and the end
                                 of the string
--------------------------------------------------------------------------------
      )                        end of look-ahead
--------------------------------------------------------------------------------
      .*                       any character except \n (0 or more
                               times (matching the most amount
                               possible))
--------------------------------------------------------------------------------
    )*                       end of grouping
--------------------------------------------------------------------------------
    \n                       '\n' (newline)
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  topic                    'topic'

Python code:

import re

l=['Biology','chem102']
IO=open('fileout.txt','w') 
IF=open('filein.txt','r') 
pattern = re.compile(fr'^(subject\s+name="(?:{"|".join(l)})".*(?:\n(?!subject\s|topic$).*)*\n)topic', re.M)
contents = IF.read()
contents = pattern.sub(r'\1', contents)
IO.write(contents)
Related