Mubramaj
Mubramaj

Reputation: 651

Python Shell or Bash: How to decrement a number in a string many times in a file

In the following code I want to decrement the number after Vec2( which is 11 in the first line below:

  new Point([84], '[',{ x: 49.22, y: 33.75 }, 4.28, 13.5, [new Vec2(11, 2)]),
  new Point([85], ']',    { x: 53.5, y: 33.75 }, 4.28, 13.5, [new Vec2(12, 2)]),
  new Point([87], '[',    { x: 57.78, y: 33.75 }, 6.42, 13.5, [new Vec2(13, 2), new Vec2(14, 2)])

Output expected:

  new Point([84], '[',{ x: 49.22, y: 33.75 }, 4.28, 13.5, [new Vec2(10, 2)]),
  new Point([85], ']',    { x: 53.5, y: 33.75 }, 4.28, 13.5, [new Vec2(11, 2)]),
  new Point([87], '[',    { x: 57.78, y: 33.75 }, 6.42, 13.5, [new Vec2(12, 2), new Vec2(13, 2)])

I have hundreds of lines like above, I want to script it in python shell or bash.

How can I do that?

Upvotes: 0

Views: 145

Answers (3)

Jack
Jack

Reputation: 6158

Well, it is mighty crude, but for a one-off you can use vi. Create a macro with

:map t /Vec2(/^Mww^X

Press the Enter key to end the macro. Then just press t as many times as you need. Or hold down the t key for a while. Just be aware that it will cycle back to the top.

N.B.: The ^M is a single character, which can go into the macro with Ctrl-V Enter. For the ^X you can just press Ctrl-x, but you need the Ctrl-V so that pressing the Enter key does not end the macro.

Upvotes: 1

choroba
choroba

Reputation: 241918

Perl to the rescue!

perl -pe 's/Vec2\(\K([0-9]+)/$1-1/ge' -- file
  • \K makes the regex engine "forget" the preceding characters, so only the substring matching the following regex is replaced
  • /e evaluates the replacement as code

Upvotes: 2

Mikhail Burshteyn
Mikhail Burshteyn

Reputation: 5012

A solution with Python and regexes:

import re

def replacer(match):
    num = int(match.group(0))
    return str(num - 1)

regex = re.compile(r'(?<=Vec2\()\d+')

with open('path/to/input.ext') as f:
    content = f.read()
result = regex.sub(replacer, content)

with open('path/to/output.ext', 'w') as f:
    f.write(result)

The regex uses lookbehind, so only the number (\d+) is included in the resulting match.

All matches in file are replaced using a function which converts the match to an integer, decrements it and converts back to a string.

Upvotes: 2

Related Questions