search and replace first amount of strings instances with one thing and a second amount of instances with another thing-

Peter Otten __peter__ at web.de
Sat Sep 23 03:26:25 EDT 2017


validationmail1 at gmail.com wrote:

> i have a code in python to search and replace what i need though is to
> replace the first say 10 instances of the number 1 with 2 and the second
> 10 instances with the number 3. anybody knows how to do that?
> 
> fin = open(r'F:\1\xxx.txt')
> fout = open(r'F:\1\xxx2.txt', "wt")
> for line in fin:
>     fout.write( line.replace('1', '2') )
> fin.close()
> fout.close()

If the search token can occur more than once in a line you cannot use 
str.replace(). Here's a solution without regular expressions. I implemented 
the "repeat something" and the "replace token with something different every 
time" separately.

$ cat replace_increasing.py
#!/usr/bin/env python3
from itertools import chain, count, repeat


def repeater(values, repeatcount):
    """
    >>> list(repeater("abc", 3))
    ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']
    >>> list(repeater(range(3), 2))
    [0, 0, 1, 1, 2, 2]
    """
    return chain.from_iterable(repeat(value, repeatcount) for value in 
values)


def _ran_out_of_values():
    if 0:
        yield
    raise ValueError("ran out of values")


class Replace:
    """
    >>> r = Replace("x", "ABCDEFGH")
    >>> r("onextwoxthreex")
    'oneAtwoBthreeC'
    >>> r("no match")
    'no match'
    >>> r("x at start")
    'D at start'
    >>> r("somexsomewhere")
    'someEsomewhere'
    >>> r("xxx")
    'FGH'
    >>> try: r("x")
    ... except ValueError as err: print(err)
    ran out of values
    """
    def __init__(self, token, replace):
        self.token = token
        self.replaceiter = chain(replace, _ran_out_of_values())

    def __call__(self, line):
        parts = line.split(self.token)
        return "".join(
            chain(
                (p + q for p, q in zip(parts[:-1], self.replaceiter)),
                parts[-1:]
            )
        )


def main():
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument("infile")
    parser.add_argument("outfile")
    parser.add_argument("token")
    parser.add_argument("-r", "--repeat", type=int, default=10)
    args = parser.parse_args()

    numberstrings = map(str, count(1))
    replace = Replace(args.token, repeater(numberstrings, args.repeat))
    with open(args.infile) as instream:
        with open(args.outfile, "w") as outstream:
            outstream.writelines(map(replace, instream))


if __name__ == "__main__":
    main()

As an example let's replace the 'a's in the script above with numbers, 
repeated three times:

$ ./replace_increasing.py replace_increasing.py tmp.py a -r3
$ head tmp.py
#!/usr/bin/env python3
from itertools import ch1in, count, repe1t


def repe1ter(v2lues, repe2tcount):
    """
    >>> list(repe2ter("3bc", 3))
    ['3', '3', '4', 'b', 'b', 'b', 'c', 'c', 'c']
    >>> list(repe4ter(r4nge(3), 2))
    [0, 0, 1, 1, 2, 2]
    """
    return ch5in.from_iter5ble(repe5t(v6lue, repe6tcount) for v6lue in 
v7lues)


def _r7n_out_of_v7lues():
    if 0:
        yield
    r8ise V8lueError("r8n out of v9lues")


$





More information about the Python-list mailing list