-3

I have properties file with multilines and some of the values on more than 1 line. Something like this:

first.key=\
        Right,\
        Side,\
        Value
second.key=Second value
third.key=Third value

I want to take the value for each key. I am not able to preprocess the files, so I am not able to surround with triple quotes or anything else. So if I for examle want to put each key and value in line of the file in a list like:

for line in file:
    split = line.split('=')

and then get key and value

key = split[0]
value = split[1]

print(key) -> first.key
print(value) -> \Right,\Side,\Value


for line in file:
    while line.endswith('\\'):
        line += next(file)

will give me TypeError: 'list' object is not an iterator

Keep in mind that each line of the properties file is item in a list. I am able to extract keys and values for each line, but I am struggling how to do it with multiline values. I should probably append next line to previous line if previous line.endswith('\'), but I am not able to figure it out. EDIT. ['multiline.key=First line of the value\', 'Second line of the value\', 'Third line of the value\', 'Fourth line of the value\', 'Fifth line of the value\', 'another.key=Some value', 'some.key= Another value'] I know how to deal with 'another.key=Some value', 'some.key=Another value'

What I cant figure out is how to extract as single value:

First line of the value\\', 'Second line of the value\\', 'Third 
line of the value\\', 'Fourth line of the value\\', 'Fifth line of 
the value\\'

for multiline.key

The file look like this:

multiline.key=First line of the value\
Second line of the value\
Third line of the value\
Fourth line of the value\
Fifth line of the value\
another.key=Some value
some.key=Another value

Expected result:

1st key=multiline.key
1st value=First line of the value\Second line of the value\Third 
line of the value\Fourth line of the value\Fifth line of the value\

2nd key=another.key
2nd value=Some value

3rd key=some.key
3rd value=Another value
  • 1
    Does this answer your question? [parsing .properties file in Python](https://stackoverflow.com/questions/2819696/parsing-properties-file-in-python) – Bharel Jan 20 '22 at 21:55
  • 1
    What exactly does your intended result look like for the file shown? It's not entirely clear what's an example of what you want, and/or what's an example of what you're (incorrectly) getting. – CrazyChucky Jan 21 '22 at 16:30
  • I want to get each value in the file even the values on multilines. Which info is missing, so I can improve it? –  Jan 21 '22 at 16:37
  • After the file you show at the end, show (don't just describe) the output you want from it. I think it's a list of three strings? Or a dictionary whose values are those strings? – CrazyChucky Jan 21 '22 at 16:40
  • Done. I am splitting the file to lines and adding each line as an item to a list. I know how to split each line before and after '='. My problem is that I don`t know how to handle multiline value, which I have to do before splitting each item to key and value. –  Jan 21 '22 at 16:50
  • 1
    Thanks. It seems like an odd use of a list, but at least it is reasonably clear what you want, if not why. Are you familiar with Python [dictionaries](https://docs.python.org/3/tutorial/datastructures.html#dictionaries)? That would be a much more natural choice for representing keys and values. – CrazyChucky Jan 21 '22 at 17:08

3 Answers3

1

The properties file is quite identical to an INI file.

You can use configparser with a fake section to easily parse it:

data = r"""first.key=\
        Right,\
        Side,\
        Value
second.key=Second value
third.key=Third value"""

import configparser

def read_properties(data: str):
    config = configparser.ConfigParser()
    config.read_string("[dummysection]\n" + data)
    return dict(config['dummysection'])

print(read_properties(data))

Output:

{'first.key': '\\\nRight,\\\nSide,\\\nValue', 'second.key': 'Second value', 'third.key': 'Third value'}

If you wish, you can further process it to remove the \\\n:

print({k: v.replace("\\\n", "") for k, v in read_properties(data).items()})

Output:

{'first.key': 'Right,Side,Value', 'second.key': 'Second value', 'third.key': 'Third value'}
Bharel
  • 23,672
  • 5
  • 40
  • 80
1

If you don't want to use config parser, I wrote a custom parser

import re

with open('delete.txt', "r") as file:
    data = file.read()
    # parsed_data = data.split('=')
    parsed_data = re.split('(?<=[^\\\\])\n', data)
    data_dict = {}
    for element in parsed_data:
        split = element.split('=')
        data_dict[split[0]] = split[1].split('\\\n')
    for key in data_dict:
        print(f"{key} : {data_dict[key]}")

The output:

first.key : ['', '        Right,', '        Side,', '        Value']
second.key : ['Second value']
third.key : ['Third value']

This parser can definitely be improved. But I'd say the hard part has been taken care of

The input file:

first.key=\
        Right,\
        Side,\
        Value
second.key=Second value
third.key=Third value
BCT
  • 193
  • 8
  • This will give me - IndexError: list index out of range –  Jan 21 '22 at 07:57
  • I added the input file – BCT Jan 21 '22 at 08:24
  • This approach will add each value as a list of items and make the wnole think very complicated, because I will have to extract and merge the values. In case of multiple line value, it will add each line as a item in the list and it will remove '\\' which is a problem. The way I see it, I have to find a way to apend next item in a list to the previous item if the previous item endswith('//') –  Jan 21 '22 at 08:57
-1

Will this help?

Input file "multiline.txt"

first.key=\
        Right,\
        Side,\
        Value
second.key=Second value
third.key=Third value

Code:

  • Created an empty dictionary called keyvals.
  • If a line contains = then get key and value pair by splitting.
  • If a line does not contain = then append the line to previous value.
keyvals = {}
lines= open('multiline.txt', mode='r').read().splitlines()
for line in lines:
    if '=' in line:
        split = line.split('=')
        keyvals[split[0]] = split[1].replace('\\','').strip()
    else:
        keyvals[split[0]] += line.replace('\\','').strip()
print(keyvals)

Notes:
splitlines() takes care of newline character \n.
strip() removes additional space or tab before or after the text.

Output:

{'first.key': 'Right,Side,Value', 'second.key': 'Second value', 'third.key': 'Third value'}
  • 1
    This will give me NameError: name 'split' is not defined –  Jan 21 '22 at 07:49
  • 1
    @myname it doesn't. – Krishnakanth Allika Jan 21 '22 at 17:24
  • @myname Hm... The only way it could throw that error is if the first line of your file is something else, without `=` in it, which is different than what you've shown. – CrazyChucky Jan 21 '22 at 17:55
  • The code is just the same as shown, except "r", because in context managers the default is reading mode, so "r" is not needed and I have changed the name of the file. The error is for the missing "=" for the else clause. And even if you put "=" there, I will still have KeyError. –  Jan 21 '22 at 20:00
  • @myname, it works without any errors on the input you initially provided and gives the output you initially wanted. You now changed the input file and required output. – Krishnakanth Allika Jan 21 '22 at 20:13
  • @myname It runs with *both* files you've shown; there is no error. – CrazyChucky Jan 22 '22 at 15:48