0

What I want to do is say I have the multi-line string:

1.10...
1.11...
1.12...
1.13...
...
1.18...

I would like to match 1.1([0-9]) and replace with 1.1(\1+1) if \1 is the captured digit from the matched pattern and (1+1) in the replace pattern makes 2, e.g. 1.11 is replaced by 1.12, 1.12 by 1.13 and so on. Is there such a feature in any regex engine/implementation that can do this sort of transformation of captured groups? I am specifically working with sed under Red Hat. Can I do it with any other tool?

4
  • perl -pe 's/^\d+\.\K(\d+)/$1 + 1/ge' Commented Jun 12 at 10:31
  • 1
    with sed and if only x0 to x8 : sed -e "s/8\$/9/" -e "s/7\$/8/" -e "s/6\$/7/" -e "s/5\$/6/" -e "s/4\$/5/" -e "s/3\$/4/" -e "s/2\$/3/" -e "s/1\$/2/" -e "s/0\$/1/" <file>. But for instance awk is a better choice for that king of thing Commented Jun 12 at 10:34
  • you can implement a decadic full adder in sed but it would be rather inefficient Commented Jun 12 at 12:57
  • 2
    What's the expected output for 1.19? Commented Jun 13 at 1:26

4 Answers 4

1

To add 1 to the number after the . on each line using any awk in any shell on every Unix box would be:

awk 'BEGIN{FS=OFS="."} {++$2} 1' file

When considering whether or not to try to use regular expressions to solve any given problem, always keep in mind this quote:

Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems.

Sign up to request clarification or add additional context in comments.

Comments

0

This might work for you (GNU sed):

sed -E '/^1\.1[0-9]/s/(...)(.)(.*)/echo "\1$((\2+1))\3"/e' file

If a line begins 1.1 followed by a digit, replace that line with an echo command that when evaluated adds 1 to the fourth character.

Or if you prefer:

sed -E 's/^(1\.1)([0-9])(.*)/echo "\1$((\2+1))\3"/e' file

Comments

0

Use this Perl one-liner:

perl -i.bak -lpe 's{^(\d+[.])(\d+)}{$1 . ($2 + 1) }e' input_file

The Perl one-liner uses these command line flags:
-e : Tells Perl to look for code in-line, instead of in a file.
-p : Loop over the input one line at a time, assigning it to $_ by default. Add print $_ after each loop iteration.
-l : Strip the input line separator ("\n" on *NIX by default) before executing the code in-line, and append it when printing.
-i.bak : Edit input files in-place (overwrite the input file). Before overwriting, save a backup copy of the original file by appending to its name the extension .bak. If you want to skip writing a backup file, just use -i and skip the extension.

s{PATTERN}{REPLACEMENT} : Replace regex PATTERN with REPLACEMENT.
^ : Matches the beginning of the line.
(\d+[.]) : Matches 1 or more digits, followed by a literal dot (.). Parentheses make it store the match in capture variable $1.
$2 + 1: The string stored in capture variable $2, evaluated as a number, plus 1.
$1 . ($2 + 1): Concatenates $1 and the result of $2 + 1, now as strings.

The regex uses this modifier:
e : Evaluate REPLACEMENT as an expression in s{PATTERN}{REPLACEMENT}.

See also:

Comments

0

Is there such a feature in any regex engine/implementation that can do this sort of transformation of captured groups?

Python's re.sub does accept function as 2nd argument, which will be furnished with Match object. Consider following example, let subexample.py content be

import re
text = "1.10...\n1.11...\n1.12...\n1.13...\n...\n1.18...\n"
def replacement(m):
    value = int(m.group(1))
    value += 1
    return "1.1%d" % value
result = re.sub(r"1[.]1([0-9])", replacement, text)
print(result)

then running python subexample.py will give following output

1.11...
1.12...
1.13...
1.14...
...
1.19...


Explanation: I prepared function replacement function which does access 1st (and only) group, convert it to numeric value (integer), increase by 1 and then prepare replacement string using % formatting. Note that [.] was used in regular expression to mean literal dot, not any character.

(tested in Python 3.12.3)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.