1

Suppose you have a textfile:

Time step #1 (t = 0 a.u. = 0 fs)
unneccessary text unneccessary text unneccessary text
...
Time step #2 (t = 10 a.u. = 0.24189 fs)
...
Time step #3 (t = 20 a.u. = 0.48378 fs)

Time step #1 (t = 0 a.u. = 0.0 fs)
...
Time step #2 (t = 10 a.u. = 0.24189 fs)
...

How can I use regular expressions in order to make the time steps continuous in the form:

Time step #1 (t = 0 a.u. = 0 fs)
unneccessary text unneccessary text unneccessary text
...
Time step #2 (t = 10 a.u. = 0.24189 fs)
...
Time step #3 (t = 20 a.u. = 0.48378 fs)

Time step #4 (t = 30 a.u. = 0.72567 fs)
...
Time step #5 (t = 40 a.u. = 0.96756 fs)
...

Generalized my question could be rephrased as:

How can a certain pattern be matched multiple times and the pattern

TIME STEP #N (t = N * 10 a.u. = N * 0.24189)  with n in range(0,5002)

be substituted?

  • Welcome to Vi and Vim! Can you describe how you want the values in parens to be adjusted? I have a solution (an idiom, really) for the first part, but the second part is unclear. Please edit to add more details. – D. Ben Knoble May 27 at 15:53
  • In the end, I would like to end up with: TIME STEP #1 (t = 0 a.u. = 0 fs) TIME STEP #2 (t= 10 a.u. = 0.24 fs) TIME STEP #3 (t = 20a.u. = 0.48 fs) and so on – Lamba May 27 at 15:54
  • To clarify, the pattern is time step t means 10*t a.u. and 0.24*t fs? – D. Ben Knoble May 27 at 15:57
  • in an abstract way: TIME STEP #N (t = 10*N a.u. = 0.24*N fs), if you mean that, yes. – Lamba May 27 at 16:00
1

There is an idiom (one example) of using an incrementing counter in :global commands combined with :s/.../\= commands. In virtually all cases, you'll start with

let counter = 0

Though you may use another number if you need to start counting from, e.g., one.

The next step is to invoke a command on the lines you care about, which generally involves

global/pattern/command | let counter += 1

Because the increment happens for each line, we can use counter to build sequences. Additionally, if command is a :substitute with the same pattern, we can use // for a shorthand.

To get expressions into a replacement, which allows us to compute arbitrary replacement strings, we use \=. I generally use a form like printf() to build the target string because I find it easier to read than string concatenation.

In the end, the full commands are

let counter = 0
global/Time step #\zs\d\+ ([^)]*)/substitute//\=printf('%d (t = %d a.u. = %f fs)', counter, 10*counter, 0.24*counter)/ | let counter += 1

Running this on your test case, I get

Time step #0 (t = 0 a.u. = 0.000000 fs)
unneccessary text unneccessary text unneccessary text
...
Time step #1 (t = 10 a.u. = 0.240000 fs)
...
Time step #2 (t = 20 a.u. = 0.480000 fs)

Then a lot of text and after a while again

Time step #3 (t = 30 a.u. = 0.720000 fs)

You may want to adjust the precision on %f (something like %.2f or %.3f, depending on how many entries you have); the default is 6.

| improve this answer | |
  • 1
    That was really helpful! Thank you also for the thorough explanation! – Lamba May 27 at 18:05
  • @Lamba you're welcome! General practice is to wait 24 hours or so before accepting an answer, but accepting an answer is a way to say "this solved my problem." Just so you know! Accepting answers – D. Ben Knoble May 27 at 18:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.