2

This might be more information than necessary to explain my question, but I am trying to combine 2 scripts (I wrote for other uses) together to do the following.

TargetString (input_file) 4FOO 2BAR

Result (output_file) 1FOO 2FOO 3FOO 4FOO 1BAR 2BAR

My first script finds the pattern and copies to file_2

pattern = "\d[A-Za-z]{3}"
matches = re.findall(pattern, input_file.read())
f1.write('\n'.join(matches))

My second script opens the output_file and, using re.sub, replaces and alters the target string(s) using capturing groups and back-references. But I am stuck here on how to turn i.e. 3 into 1 2 3.

Any ideas?

physlexic
  • 826
  • 2
  • 9
  • 21

2 Answers2

3

Assuming your numbers are between 1 and 9, without regex, you can use a list comprehension with f-strings (Python 3.6+):

L = ['4FOO', '2BAR']
res = [f'{j}{i[1:]}' for i in L for j in range(1, int(i[0])+1)]

['1FOO', '2FOO', '3FOO', '4FOO', '1BAR', '2BAR']

Reading and writing to CSV files are covered elsewhere: read, write.

More generalised, to account for numbers greater than 9, you can use itertools.groupby:

from itertools import groupby

L = ['4FOO', '10BAR']

def make_var(x, int_flag):
    return int(''.join(x)) if int_flag else ''.join(x)

vals = ((make_var(b, a) for a, b in groupby(i, str.isdigit)) for i in L)

res = [f'{j}{k}' for num, k in vals for j in range(1, num+1)]

print(res)

['1FOO', '2FOO', '3FOO', '4FOO', '1BAR', '2BAR', '3BAR', '4BAR',
 '5BAR', '6BAR', '7BAR', '8BAR', '9BAR', '10BAR']
jpp
  • 159,742
  • 34
  • 281
  • 339
  • 1
    What about `10Foo`? (Update: Did not see the clarification in last line) – tobias_k Jul 26 '18 at 16:25
  • 1
    `Assumes your numbers are between 1 and 9.`. I'd like more clarity from OP to see whether this is actually a problem. – jpp Jul 26 '18 at 16:26
  • Granted, given OP's examples this is perfectly fine. However, the first line could be understood as "you do not need regex, but only if you have Python 3.6+". – tobias_k Jul 26 '18 at 16:28
  • @jpp thank you! this gives me an idea on how to approach, i was getting tunneled into what I already had.. the integers go into double digits so I would need to adjust to go beyond 1-9 – physlexic Jul 26 '18 at 16:33
  • @physlexic, I've updated for a more generalized solution. – jpp Jul 26 '18 at 16:41
3

This simple example doesn't need to use regular expression, but if you want to use re anyway, here's example (note: you have minor error in your pattern, should be A-Z, not A-A):

text_input = '4FOO 2BAR'

import re

matches = re.findall(r"(\d)([A-Za-z]{3})", text_input)

for (count, what) in matches:
    for i in range(1, int(count)+1):
        print(f'{i}{what}', end=' ')

print()

Prints:

1FOO 2FOO 3FOO 4FOO 1BAR 2BAR 

Note: If you want to support multiple digits, you can use (\d+) - note the + sign.

Andrej Kesely
  • 168,389
  • 15
  • 48
  • 91