0

I've just recorded my zsh command trace into a file, in a list of timestamp-prefixed lines like this:

1728667090.254060000+_pyenv_virtualenv_hook:1> local ret=0
1728667090.254181000+_pyenv_virtualenv_hook:2> [ -n '' ']'
1728667090.255413000+_pyenv_virtualenv_hook:5> pyenv sh-activate --quiet
1728667090.256157000+pyenv:1> local command
1728667090.256659000+pyenv:2> command=sh-activate 

There are hundreds of lines.

Now I would like to replace the starts of the lines with the difference between the timestamps

0+_pyenv_virtualenv_hook:1> local ret=0
0.0001199245453+_pyenv_virtualenv_hook:2> [ -n '' ']'
0.00123000145+_pyenv_virtualenv_hook:5> pyenv sh-activate --quiet
0.0007400512695+pyenv:1> local command
0.0004999637604+pyenv:2> command=sh-activate 

How can I do that in vim?

I can pass it to external awk for example

:%!awk -F+ -v OFS=+ '{ current = $1 ; $1=""; printf "%.9f%s\n", current - prev, $0 ; prev = current }'

But that was a difficult command line to design, so I'm looking for simpler ways that might require less knowledge of other tools and syntaxes.

3
  • Do you still have something open in your question? How can we help you further? Otherwise maybe could you accept one of the solutions using the v button next to the arrow voting buttons. It allow the question to rest :-) Commented Oct 13 at 14:16
  • @VivianDeSmedt I've upvoted your answer, but I feel like it's even more complicated, less comprehensible to me, than the awk one I already came up with
    – user9024
    Commented Oct 13 at 15:17
  • You are right :-) But on the other hand your question was about: "How to do it with Vim" ;-) Commented Oct 13 at 16:12

2 Answers 2

1

If you don't mind doing it in two passes:

%s/\ze+/\='-' .getline(max([line('.')-1, 1]))[0:19]

gives you:

1728667090.254060000-1728667090.254060000+_pyenv_virtualenv_hook:1> local ret=0
1728667090.254181000-1728667090.254060000+_pyenv_virtualenv_hook:2> [ -n '' ']'
1728667090.255413000-1728667090.254181000+_pyenv_virtualenv_hook:5> pyenv sh-activate --quiet
1728667090.256157000-1728667090.255413000+pyenv:1> local command
1728667090.256659000-1728667090.256157000+pyenv:2> command=sh-activate 

You can then evaluate the subtraction:

%s/[^+]*/\=printf('%.9f', eval(submatch(0)))

giving

0.000000000+_pyenv_virtualenv_hook:1> local ret=0
0.000120878+_pyenv_virtualenv_hook:2> [ -n '' ']'
0.001232147+_pyenv_virtualenv_hook:5> pyenv sh-activate --quiet
0.000743866+pyenv:1> local command
0.000502110+pyenv:2> command=sh-activate 
1
  • Clever, evaling a subtraction.
    – D. Ben Knoble
    Commented Oct 23 at 16:01
0

Vimscript solution

You could do:

let b = str2float(getline(1))
for i in range(1, line('$'))
  let a = str2float(getline(i))
  execute i . 's/^\d\+\.\d*/\=printf("%.9f", str2float(submatch(0)) - b)'
  let b = a 
endfor

It can be put in a one liner as:

let b = str2float(getline(1)) | for i in range(1, line('$')) | let a = str2float(getline(i)) | execute i . 's/^\d\+\.\d*/\=printf("%.9f", str2float(submatch(0)) - b)' | let b = a | endfor

Regular Expression

Or using regular expressions:

g/^/m0
%s/\v^(\d+\.\d*)(.*)(\n(\d+\.\d*))@=/\=printf("%.9f", str2float(submatch(1)) - str2float(submatch(4))) . submatch(2)
g/^/m0

Where:

  • g/^/m0 make the file upside down
  • %s/\v^(\d+\.\d*)(.*)(\n(\d+\.\d*))@=/\=printf("%.9f", str2float(submatch(1)) - str2float(submatch(4))) . submatch(2) do the subtractions
  • g/^/m0 revert back the order of the lines

Remarks:

  • @= is preferred instead over \zs to not consume the token of the next line such that the replacement is done on all lines
1
  • @D.BenKnoble thanks for pointing that! I miss read the question. I'll correct the answer. Commented Oct 12 at 15:21

Your Answer

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