-1

I'm quite new to python and would appreciate some assistance/suggestions.

I have a text file which I need to add a new line to if some conditions are/aren't met. I need to look over each line for lines that contain "rightid=" followed by either an IP address or a name.

If the line does NOT include an IP address after "rightid=" then add a new line underneath with some text, if it does contain an IP then do nothing.

To clarify, I need a new line added to the text file underneath the lines that contain "rightid=" and NOT an IP address. So if it sees "rightid=192.168.1.1" (or any IP) then ignore it, if it sees "rightid=randomname" then add a new line in the text file underneath the line in question with some text.

I'm assuming I should use a regular expression of some sort but I'm drawing a blank on how to structure the code and then how to add a new line underneath

Below is as far as I've got

with open (filename, 'r+') as file:
        data = file.read()
        for line in data:
            if "rightid=" in line:

Any help would be amazing.

Thanks

MultiPass
  • 1
  • 2
  • Possible duplicate of [Regular expression for IP Address Validation](https://stackoverflow.com/questions/10006459/regular-expression-for-ip-address-validation) – CDJB Nov 26 '19 at 14:52
  • This answer may be appropriate for Python-realization of such task https://stackoverflow.com/questions/59006152/find-strings-and-subtring-from-the-wordlist/59006375#59006375 – Alex Nov 26 '19 at 15:08

2 Answers2

0

The docs: https://docs.python.org/3/library/re.html

import re

with open (filename, 'r+') as file:
  data = file.read()
  new_data = ''
  for line in data:
  if "rightid=" in line:
    ip_exists=re.match(r"[^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$]", line)
    if not ip_exists:
      new_data += line
      new_data += # Extra Info Here
    else:
      new_data += line
  with open(filename, 'w') as file:
    file.write(new_data)
  • This may not be the correct ip address regular expression. If you wish to change it, here's another good resource: https://stackoverflow.com/questions/10086572/ip-address-validation-in-python-using-regex –  Nov 26 '19 at 15:16
  • No, no, no. Any data that is written via '#add new line with text here` will be going to the end of file, *not* underneath the line that had "righid=". And the user needs to match an ip address *or* a name. – Booboo Nov 26 '19 at 16:16
  • Thanks for the help, this almost looks like what I'm after. To clarify I need a new line added to the text file underneath the lines that contain "rightid=" and NOT an IP address. So if it sees "rightid=192.168.1.1" (or any IP) then ignore it, if it sees "rightid=randomname" then add a new line in the text file underneath the line in question with some text – MultiPass Nov 26 '19 at 16:26
0

Ideally the following would be the solution (it's not, but the next coding example is):

import re

regex = re.compile(r'rightid=\D+')
with open (filename, 'r+', buffering=0) as f:
    for line in f:
        if regex.search(line):
            print('Extra line', file=f)

Note the attempt to open the input file in non-buffered mode by specifying buffering=0. In this mode you would hope that you are only reading the file one line at a time so that the print statement would result in outputting the extra line immediately under the line just read. But this mode is only available for binary files. So, to work in binary mode we have use byte character literals:

import re, os

regex = re.compile(rb'rightid=\D+')
with open (filename, 'rb+', buffering=0) as f:
    for line in f:
        if regex.search(line):
            f.write(b'Extra line' + os.linesep.encode())

If you insist on working with strings, then:

import re

regex = re.compile(r'rightid=\D+')
with open (filename, 'r') as f:
    lines = [line for line in f]
with open(filename, 'w') as f:
    for line in lines:
        print(line, file=f, end='')
        if regex.search(line):
            print('Extra line', file=f)

The file is first read in and split info lines and then reopened for output rewriting the entire file. The danger here is that the computer could go down in the middle of the operation. You should therefore either (1) first make a backup of the original file (my choice) or (2) write the output to a new, temporary file and on successful completion delete the original and rename the temporary file.

Booboo
  • 38,656
  • 3
  • 37
  • 60
  • Cheers for the help Ronald. I went with your 2nd example and changed the regex. regex = re.compile(r'rightid=[^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$]') – MultiPass Nov 27 '19 at 11:03
  • @MultiPass I don't think you are using `[^]` correctly. If you are trying to find those lines that do not have `rightid=` followed by an IP address, have your regex *match* (you will actually use `re.search`) a `rightid=` followed by an IP address and when it fails, you know to put out the extra line. Since you said the only other choice was `rightid=` followed by a name, which I took to mean it began with a word character, I took the opposite approach. – Booboo Nov 27 '19 at 11:56
  • I did update my regex -- I had a bit of a brain freeze having forgotten that `\w` can also match digits as well as alpha characters. I have replaced `\w+` with `\D+`, which is one or more non-digit characters. You really don't even need the `+`. Sorry for the confusion. – Booboo Nov 29 '19 at 20:07