Is it possible to replace Sed with arithmetic?

The file I need to modify contains the following:

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

I need a file so that the values ​​for block , size are divided by 2, and the values ​​for start , the length will be multiplied by 2.

Since I have to make such changes for a whole group of files, I am considering using Sed to do the replacement work for me. But I'm not sure that the calculations are allowed in the process of matching and replacing.

+7
source share
4 answers

I always try to solve every problem with tags using sed . But it would be so easy to accomplish what you are trying to do with awk . (And using sed in this case is too complicated). 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 
+8
source

Perl is useful here:

 perl -pe ' s{(\D+)(\d+)(\D+)(\d+)(\D+)(\d+)(\D+)(\d+)} {$1 . $2/2 . $3 . $4/2 . $5 . $6*2 . $7 . $8*2}e ' file 

If you want to edit your files in place, perl has the -i option, for example sed.

+5
source

(The right tool for this is awk, but for the pleasure of doing sed ...)

This is possible in sed. After all, multiplying by 2 represents replacing the last digit in accordance with some simple rules:

  • 0 β†’ 0
  • 1 β†’ 2
  • 2 β†’ 4
  • 3 β†’ 6
  • ...
  • 8 β†’ 16
  • 9 β†’ 18

To take care of the hyphen, each rule must be written twice.

This sed script, which can be run with a sed -f script , multiplies by 2 the numbers of all lines in 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, and not from 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 does 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 how the Turing Machine implementation was implemented, so I try to remember that everything that can be done using the programming language can be done in sed. This, of course, does not mean that sed is a good tool in all situations.

+5
source

Do not think it is possible. See http://www.delorie.com/gnu/docs/sed/sed_15.html .

However, if you have only a small set of possible values ​​for a block, size, start and length, it may be the fastest for hard coding the necessary substitutions. Probably the next easiest option is to use awk , but it cannot modify files in place.

0
source

All Articles