0

I want to be able to open a file, locate a specific string and then append a string to that specific line.

So far, I have:

import errno
import glob

path = '/path/to/key_files/*.txt'
SubjectName = 'predetermined'

files = glob.glob(path)
for filename in files:
    try:
        with open(filename, 'r+') as f:
           for line in f:
               if SubjectName in line:
                   print(line)
    except IOError as exc:
        if exc.errno != errno.EISDIR:
            raise

Which prints a line from the text file containing the string I specified, so I know all the code works in terms of locating the correct line. I now want to add the string ',--processed\n' to the end of the located line, as opposed to appending it to the very end of the file. Is there a way to do this?

Louise Cullen
  • 97
  • 1
  • 8
  • Possible duplicate of [Insert line at middle of file with Python?](https://stackoverflow.com/questions/10507230/insert-line-at-middle-of-file-with-python) – tgikal Jun 18 '19 at 18:27
  • @tgikal kind of, but I don't want to insert a new line, I want to add to an existing one. It could be the same solution, but it seems a little different to me! – Louise Cullen Jun 18 '19 at 18:30
  • Inserting or appending is just modifying data in a particular place in the file data, it's the same operation. In the selected answer https://stackoverflow.com/a/10507291/4777984, instead of `contents.insert(index, value)` you would use `contents[index] = contents[index].strip('\n') + ',--processed\n'` instead. – tgikal Jun 18 '19 at 18:38
  • Possible duplicate of [Is it possible to modify lines in a file in-place?](https://stackoverflow.com/questions/5453267/is-it-possible-to-modify-lines-in-a-file-in-place) – wwii Jun 18 '19 at 18:48
  • And maybe this one: [Search and replace specific line which starts with specific string in a file](https://stackoverflow.com/questions/39386384/search-and-replace-specific-line-which-starts-with-specific-string-in-a-file) – wwii Jun 18 '19 at 18:59
  • @wwii yes, it seems to be basically a duplicate of both of those! The only thing is that the answer I received and accepted is pretty different than the answers to the other questions, and could be useful to other people. Will marking it as a duplicate make it hard for people to see the answer to my question? – Louise Cullen Jun 18 '19 at 19:06
  • No but there are many other possible duplicates. Having these links in the comments will point someone to those if they find yours while searching. It won't get marked duplicate unless others vote on it. – wwii Jun 18 '19 at 19:27

2 Answers2

2

You can use re.sub. After reading the file with f.read() you can use see f.seek(0) to rewind to the beginning and use f.write() to write your new content (you need to open the file with r+ flag):

Content of the file.txt:

Line1
Line2
Line3
Line4

Script:

import re

SubjectName = 'Line3'

with open('file.txt', 'r+') as f:
    s = f.read()
    new_s = re.sub(r'^(.*{}.*)$'.format(re.escape(SubjectName)), lambda g: g.group(0) + ',--processed', s, flags=re.MULTILINE)
    f.seek(0)
    f.write(new_s)

Afer running the file.txt contains:

Line1
Line2
Line3,--processed
Line4
Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91
  • That worked, thank you! Do you mind explaining a bit more what you did for new_s? – Louise Cullen Jun 18 '19 at 18:53
  • @LouiseCullen I used regular expression to substitute old string with new one - in this case `Line3` with `Line3;--processed`. The key is having set flag to `re.MULTILINE` to having the `^` and `$` symbols work for each line. https://regex101.com/r/bLvLNa/1 – Andrej Kesely Jun 18 '19 at 18:59
0

Yes, there is a way to do this. Once you find the file, close it. Then open it again and create a new text file. read the input file line by line and write each line to the output file. When you reach the line containing the specified string, append your desired added text to that line when you copy it to the output file. Then copy the rest of the input file to the output file. You may want to keep examining each line--your specified text may be in more than one line.

Note that you cannot just append into the middle of a file. The encoded characters sit is particular places in the file, and they will not just move slightly to add a few more characters in the middle. You almost certainly need to make a new file. Of course, when you are done you could delete the input file and rename the output file.

The only way you could avoid the output file is if there is "blank space" at the end of the target line, where you could overwrite your new text. This is very unlikely to be true, unless it was planned in advance. If it were planned, you could open the input file for writing, seek the proper position, then write your new text which would overwrite any old text at that location.

Rory Daulton
  • 21,934
  • 6
  • 42
  • 50