vim substitution with mathematical expression
Asked Answered
P

2

5

I need to replace following line:

[rescap] l=1.2u w=1.5u 

by

[rescap] l=1.2u w=1.5u r=0.8k

value of r 0.8k is l/w

I am trying in vim (already done in perl but wanted to implement using vim)

:s/l=\\(.\*\\)u w=\\(.\*\\)u/l=\1u w=\2u r=\1*\2k/

but it does not evaluate expression and prints:

[rescap] l=1.2u w=1.5u r=1.2*1.5k

If I try \= which evaluates expression it assumes l and w as variable and throws out error.

:s/l=\\(.\*\\)u w=\\(.\*\\)u/\=l=\1u w=\2u r=\1*\2/    

I have to run above expression using vim -s scriptfile through many files. just need to figure out the above substitution statement.

Pegasus answered 14/6, 2016 at 7:19 Comment(0)
R
5

You're looking for:

%s#\vl\=([0-9.]+)u\s+w\=([0-9.]+)u\zs.*#\=' r='.string(eval(submatch(1))/eval(submatch(2))).'u'

The important things are:

  • \= that tells you'll be inserting an expression -- the 3rd one (the first two are quirks induced by my use of very-magic regex with \v) -> :h :s\=
  • submatch() to access \1 and \2
  • eval() to convert the submatches into floating point numbers, and string() to convert it back
  • also note that in order to insert text after \=, you need to explicitly build a string

Then, I've used:

  • \v to simplify the regex,
  • :s# instead of :s/ to simplify the replacement expression as I need / to compute a division,
  • \zs to simplify the replacement expression as well.

Last need to know piece of information, to reach the documentation related to regex/pattern, prepend what you are looking for with a slash -> :h /\v, :h /\zs

Rowney answered 14/6, 2016 at 7:52 Comment(2)
Thanks Luc . Exactly the way i wanted. Thanks a lot.Pegasus
@Pegasus pls accept the answer if it really solved your problem. That's the way you say "thank" at SOGlobeflower
S
2

The following command will also work:

s#\vl\=(\d+\.\d+)u w\=(\d+\.\d+)u#\=printf('%s r=%.1fk', submatch(0), str2float(submatch(1))/str2float(submatch(2)))  

Some explanation:

  • submatch(0) will contain all the matched string
  • str2float() is used to convert string to float type
  • printf() is to used for ease of control of output string format.
Screw answered 8/12, 2020 at 9:34 Comment(1)
Nice simplification with printf(). Note: there is a little limitation in this solution: it won't accept integers -- while my regex accepts incorrect numbers like 1.1.2.Rowney

© 2022 - 2024 — McMap. All rights reserved.