vegedezozu
vegedezozu

Reputation: 75

Find, convert and replace some text but keep remaining text

I have the following text file:

8/1 text1 1/5 text2 9/2
4/9 text1 3/1 text2 9/2

I would like to convert all of the fractions to be decimals (odds), but maintain the format and the unconverted text, so after conversion:

9.0 text1 1.2 text2 5.5
1.44 text1 4.0 text2 5.5

I can convert the fractions to decimals using the code below, but I can't figure out how to maintain the format and unconverted text:

import os
import re
from fractions import Fraction
import fileinput
import sys

def main():
    text = open('text.txt').read()
    regex = re.findall("\d/\d", text)
    for dec_odd in regex:
        dec_odd = Fraction(dec_odd)
        dec_odd = float(dec_odd)
        dec_odd = dec_odd +1
        print(dec_odd)

if __name__ == "__main__":
    main()

I have tried to loop through each line and convert one by one but again struggling to only convert the fraction and not the full line (and the mixing up of types):

    for line in fileinput.input("text.txt", inplace = 1):
        frac_odd = re.search("\d/\d", line)
        dec_odd = Fraction(frac_odd)
        dec_odd = float(dec_odd)
        print(line.replace(frac_odd, dec_odd))

Upvotes: 3

Views: 84

Answers (2)

cdlane
cdlane

Reputation: 41905

I believe you were on the right track but re.search() doesn't return a str, it returns a match object from which you need to extract the str you want:

import re
from fractions import Fraction

text = open('text.txt').read()

fraction = re.search(r"\d+/\d+", text)

while fraction:
    string = fraction.group(0)
    decimal = format(1.0 + float(Fraction(string)), '.3')
    text = text.replace(string, decimal)
    fraction = re.search(r"\d+/\d+", text)

print(text, end='')

OUTPUT

% python3 test.py
9.0 text1 1.2 text2 5.5
1.44 text1 4.0 text2 5.5
%

Upvotes: 1

Andrej Kesely
Andrej Kesely

Reputation: 195573

You can use re.sub():

import re

data = '''8/1 text1 1/5 text2 9/2
4/9 text1 3/1 text2 9/2'''

def format_fraction(a, b):
    s = '{:.3g}'.format(float(a) / float(b) + 1)
    if '.' not in s:
        return s + '.0'
    return s

s = re.sub(r'\b(\d+)/(\d+)\b', lambda g: format_fraction(g.group(1), g.group(2)) , data)
print(s)

Prints:

9.0 text1 1.2 text2 5.5
1.44 text1 4.0 text2 5.5

Upvotes: 3

Related Questions