Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sed substitution possible with arithmetic involved?

Tags:

regex

sed

File I need to modify contains the following:

block: 16, size: 16, start: 8, length: 4

I'd like the file so that values for block, size will be divided by 2 while values for start, length will be multiplied by 2.

Since I have to make such modifications for a whole bunch of files, I am considering using Sed to do the substitution work for me. But I'm not sure calculations are allowed in the matching and substituting process.

like image 289
Terry Li Avatar asked Aug 05 '11 15:08

Terry Li


2 Answers

I always try to solve every problem tagged with sed using sed. But here it would be so easy to accomplish what you are trying to do with awk. (And the use of sed in this case is too difficult.) So, here is my solution using awk:

$ echo "block: 16, size: 16, start: 8, length: 4" | awk '{
    printf "%s %d, %s %d, %s %d, %s %d\n", $1, $2/2, $3, $4/2, $5, $6*2, $7, $8*2
}'
block: 8, size: 8, start: 16, length: 8
like image 106
brandizzi Avatar answered Oct 14 '22 07:10

brandizzi


(The right tool to do this is awk, but for the fun of a sed exercise...)

It is possible in sed. After all, a multiplication by 2 is set of substitution of the last digit according to some simple rules:

  • 0 --> 0
  • 1 --> 2
  • 2 --> 4
  • 3 --> 6
  • ...
  • 8 --> 16
  • 9 --> 18

To take care of the carry digit, each rules should be written twice.

This sed script, that can be run with sed -f script, do the multiplication by 2 of all the numbers on the input lines:

s/$/\n\n/
:loop
s/0\n1\n/\n\n1/;t loop
s/0\n\n/\n\n0/;t loop
s/1\n1\n/\n\n3/;t loop
s/1\n\n/\n\n2/;t loop
s/2\n1\n/\n\n5/;t loop
s/2\n\n/\n\n4/;t loop
s/3\n1\n/\n\n7/;t loop
s/3\n\n/\n\n6/;t loop
s/4\n1\n/\n\n9/;t loop
s/4\n\n/\n\n8/;t loop
s/5\n1\n/\n1\n1/;t loop
s/5\n\n/\n1\n0/;t loop
s/6\n1\n/\n1\n3/;t loop
s/6\n\n/\n1\n2/;t loop
s/7\n1\n/\n1\n5/;t loop
s/7\n\n/\n1\n4/;t loop
s/8\n1\n/\n1\n7/;t loop
s/8\n\n/\n1\n6/;t loop
s/9\n1\n/\n1\n9/;t loop
s/9\n\n/\n1\n8/;t loop
s/\n1\n/\n\n1/;t loop
s/\(.\)\n\n/\n\n\1/;t loop
s/^\n\n//

Dividing an even number by 2, is the same logic, but from left to right instead of right to left:

s/^/\n\n/
:loop
s/\n1\n0/5\n\n/;t loop
s/\n\n0/0\n\n/;t loop
s/\n1\n1/5\n1\n/;t loop
s/\n\n1/\n1\n/;t loop
s/\n1\n2/6\n\n/;t loop
s/\n\n2/1\n\n/;t loop
s/\n1\n3/6\n1\n/;t loop
s/\n\n3/2\n1\n/;t loop
s/\n1\n4/7\n\n/;t loop
s/\n\n4/2\n\n/;t loop
s/\n1\n5/7\n1\n/;t loop
s/\n\n5/2\n1\n/;t loop
s/\n1\n6/8\n\n/;t loop
s/\n\n6/3\n\n/;t loop
s/\n1\n7/8\n\n/;t loop
s/\n\n7/3\n1\n/;t loop
s/\n1\n8/9\n\n/;t loop
s/\n\n8/4\n\n/;t loop
s/\n1\n9/9\n1\n/;t loop
s/\n\n9/4\n1\n/;t loop
s/\n1\n/5\n\n/;t loop
s/\n\n\(.\)/\1\n\n/;t loop
s/\n\n$//

Combining those, this script do the job:

h
s/, start.*//
s/^/\n\n/
t loopa
:loopa
s/\n1\n0/5\n\n/;t loopa
s/\n\n0/0\n\n/;t loopa
s/\n1\n1/5\n1\n/;t loopa
s/\n\n1/\n1\n/;t loopa
s/\n1\n2/6\n\n/;t loopa
s/\n\n2/1\n\n/;t loopa
s/\n1\n3/6\n1\n/;t loopa
s/\n\n3/2\n1\n/;t loopa
s/\n1\n4/7\n\n/;t loopa
s/\n\n4/2\n\n/;t loopa
s/\n1\n5/7\n1\n/;t loopa
s/\n\n5/2\n1\n/;t loopa
s/\n1\n6/8\n\n/;t loopa
s/\n\n6/3\n\n/;t loopa
s/\n1\n7/8\n\n/;t loopa
s/\n\n7/3\n1\n/;t loopa
s/\n1\n8/9\n\n/;t loopa
s/\n\n8/4\n\n/;t loopa
s/\n1\n9/9\n1\n/;t loopa
s/\n\n9/4\n1\n/;t loopa
s/\n1\n/5\n\n/;t loopa
s/\n\n\(.\)/\1\n\n/;t loopa
s/\n\n$//
H
g
s/.*, start/, start/
s/\n.*//
s/$/\n\n/
t loopb
:loopb
s/0\n1\n/\n\n1/;t loopb
s/0\n\n/\n\n0/;t loopb
s/1\n1\n/\n\n3/;t loopb
s/1\n\n/\n\n2/;t loopb
s/2\n1\n/\n\n5/;t loopb
s/2\n\n/\n\n4/;t loopb
s/3\n1\n/\n\n7/;t loopb
s/3\n\n/\n\n6/;t loopb
s/4\n1\n/\n\n9/;t loopb
s/4\n\n/\n\n8/;t loopb
s/5\n1\n/\n1\n1/;t loopb
s/5\n\n/\n1\n0/;t loopb
s/6\n1\n/\n1\n3/;t loopb
s/6\n\n/\n1\n2/;t loopb
s/7\n1\n/\n1\n5/;t loopb
s/7\n\n/\n1\n4/;t loopb
s/8\n1\n/\n1\n7/;t loopb
s/8\n\n/\n1\n6/;t loopb
s/9\n1\n/\n1\n9/;t loopb
s/9\n\n/\n1\n8/;t loopb
s/\n1\n/\n\n1/;t loopb
s/\(.\)\n\n/\n\n\1/;t loopb
s/^\n\n//
H
g
s/[^\n]*\n//
s/\n//

(Much easier in awk thought.)

Note: I once saw a Turing Machine implementation is sed, so I try to remember that anything that can be done with a programming language can be done in sed. That of course does not mean that sed is the good tool in all situations.

like image 44
jfg956 Avatar answered Oct 14 '22 06:10

jfg956