-4

I have a long paragraph of text with a number in it. It roughly look like this:

aaaaaaaaaaaaaa100bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccc100ddddddddddddddddd

I need to show this paragraph in a series of files, but in each file, the number is 10 higher than its predecessor.
For example, in the file 1.txt, it looks like what I've shown above, but in 2.txt, it should look like:

aaaaaaaaaaaaaa110bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccc110ddddddddddddddddd

in 3.txt, it should be like:

aaaaaaaaaaaaaa120bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccc120ddddddddddddddddd

The text should always be the same; only the number is increasing by 10 in every new file. Also, the file name, which is a number, should increase.

I've been doing this by hand, but I need to increase the number from 100 to 1000, so it's a daunting job! I wonder if there's a command that can do this job on Linux?

1

Here is a simple Python 3 script which adds 10 to each number.

#!/usr/bin/env python3

import fileinput
import re

rx = re.compile(r'(\d+)')
for line in fileinput.input():
    parts = rx.split(line.rstrip('\n'))
    if len(parts) > 1:
        for i in range(1, len(parts), 2):
            parts[i] = str(int(parts[i]) + 10)
        line = "".join(parts)
    print(line)

This assumes that every line begins with a non-number. It's not hard to change to be slightly more flexible but this seemed to solve the job for now.

To call this from a Bash script, simply save it in a file and chmod a+x filename.py. So if you saved it in ./splitnum.py that's the command to run it, once you have made sure it has execute permission.

Here's a Perl one-liner:

perl -lne '@s = split(/(\d+)/); for($i=1;$i<=$#s;$i+=2) { $s[$i] += 10 }; print(join("", @s))'
  • just had a check on my machine, and it says it has python 2, not 3, but anyway, I'll have a try – OhLook Feb 28 at 15:34
  • If you can't install Python 3, check out the Perl one-liner I added. – tripleee Feb 28 at 16:23
  • I'm trying to install Python 3....This Perl solution indeed looks simple! But why do you say $i+=2, not $i+=1? – OhLook Feb 28 at 16:29
  • And in your answer, where do I paste my template text? – OhLook Feb 28 at 17:13
  • And in your two solutions, which part tells it to add to 1000? Which part tells it to increase the number in the file name by 1? – OhLook Feb 28 at 17:21
0

I think the bash solution to this would be a nightmare. It's certainly doable, particularly if you're open to using awk, but then that's not really bash either, so here's some python

from argparse import ArgumentParser

parser = ArgumentParser()
parser.add_argument('--template', required=True, help="Template file")
parser.add_argument('--start', default=0, help="Number to begin counting from")
parser.add_argument('--stop', default=100, help="Number to end at")
parser.add_argument('--step', default=10, help="Number to increment by")
args = parser.parse_args()

for i in range(args.start, args.stop, args.step):
    with open('{}.txt'.format(i)) as pfile:
        pfile.write(args.template.format(count=i))

You can run this by passing '--start' as the number to start at, '--stop' as the number to stop at, and '--step' as the number to increment by. You can substitue your paragraph by replacing the text in the paragraph variable at the top of the script or by putting your text in a separate file and pass the name of the file using '--template'. Make sure to use {count} everywhere you need the number in the template.

  • 1
    This is crazy complicated. A Python script to do this could be done in just a little more than the corresponding Awk script and depending on jinja2 is just outrageous. – tripleee Feb 28 at 14:32
  • 1
    @tripleee So is it possible to call out python in bash? I mean, to mix bash with python? But I guess if I write #!/bin/bash, I can't use any python script under it, right? – OhLook Feb 28 at 14:49
  • @tripleee I removed jinja2, been using it a ton lately so its just the default for me right now, but you're right, it's way heavy than necessary for this task. To simplify thing i removed the template string from the script and made the template file a requirement. I'm curious how else you'd squash things? – smokes2345 Feb 28 at 16:11
  • 1
    @OhLook It's possible to call python from a bash script. You can call python <filename> or there's also a way to run it so that it will accept code on stdin (you can pipe code in from other processes). – smokes2345 Feb 28 at 16:29
  • 1
    argparse has been there from the begining, and that's a core python module too, should be included with your distribution, no extra pip install necessary, if it's not there your installation is jacked up – smokes2345 Mar 1 at 14:31
0

If the number is always the first number of a line and your file just has one line, you can do this with a simple one-liner:

i=100; for k in $(seq 100 10 1000); do sed "s/$i/$k/g" file > file.$k; done 

This assumes an original input file called file with the following contents:

$ cat file 
aaaaaaaaaaaaaa100bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccccccccccccccccccccccccccccccccccccc100ddddddddddddddddd

And will produce file.100, file.110 . . . file.1000.


Of course, this will take a few seconds since it needs to run a separate command on each file. For a more efficient approach, you could use a perl command instead:

perl -ne 'for ($i=110;$i<=1000;$i+=10){s/(\d+)/$i/eg; open($fh,">","file.$i");  print $fh "$_" }' file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.