Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shifting decimal point using vim, shell or python

Tags:

python

shell

vim

I have a .pl file that consists of an unstructured header and some specific X Y Z structure. The header has no "." in there. Below you can find a snippet of this file:

Header (in total 29 lines)
ILINE
VRTX 1 545057.78564453125 3800905.201171875 -15000 
VRTX 2 545184.49072265625 3800765.451171875 -15000 
VRTX 3 545310.91650390625 3800625.970703125 -15000 
SEG 1 2 
SEG 2 3 
ILINE
VRTX 136 551295.84606933594 3799015.443359375 -15000 
VRTX 137 551293.82849121094 3798841.880859375 -15000 
VRTX 138 551290.57849121094 3798661.892578125 -15000  
SEG 136 137 
SEG 137 138 

What I like to achieve is to shift the decimal point of my X and Y values to the left like this:

VRTX 1 5450.5778564453125 38009.05201171875 -15000 
VRTX 2 5451.8449072265625 38007.65451171875 -15000 
VRTX 3 5453.1091650390625 38006.25970703125 -15000

I think that regular expressions could help but I have no experiences in that using Python nor Shell. Any help is appreciated.

like image 276
S.A Avatar asked Dec 17 '22 22:12

S.A


2 Answers

A copy and paste friendly vim solution

:g/VRTX/normal f.xhhP;xhhP

explanation:

  • :g/{pattern}/command - executes command on every line matching pattern. In this case every VRTX line
  • normal - the commands we want to execute are normal mode commands
  • f. - find the first dot in current line
  • xhhP - cut such character, move left two times, paste
  • ; - find next occurrence
  • xhhP - move dot again
like image 144
Francesco Avatar answered Jan 06 '23 06:01

Francesco


Since there is a vim tag on the question:

/\.
qaqqanx2hi!<esc>@aq
@a
:%s/!/./g

Assuming there is no ! in the text, else you have to substitute it with a different character(s). Of course there are other solutions in vim, but that's the simplest which I can think of right now.

Breakdown:

 /\.                  " searches every `.` in the file 
                      " (and "marks" them as searchresults)

qaqqanx2hi!<esc>@aq   " Our macro we use:
qaq                   " records an empty macro into register a 
                      " (This ensures the register is empty)
   qa                 " This starts recording a macro into register a again
     nx2hi!<esc>      " `n` jumps to the next search result,  
                      " `2hxhi!<esc>` inserts a `!` 2 chars left of where
                      " the `.` has been, and exits insert mode
                @a    " calls the macro at register `a`, since we emptied it,
                      " nothing happens yet, but once we save this macro it will
                      " be in register `a`. So it will call itself until it 
                      " reaches an abort conditions (no more `.` found in the
                      " text, thats why we replace `.` with `!` here, else
                      " the macro would move the `.` over and over to the left
                  q   " Stops recording the macro and saves it (to register `a`)

@a                    " calls the macro in register `a`

:%s/!/./g             " This just replaces all `!` in the file with `.`

Possible cleaner solution: Use nowrapscan (thanks @Francesco)

/\.
:set nows
qaqqax3hpn@aq
@a
:set ws

Note: The Macro changes order a bit. We must first change the position of the . and then jump to the next search-occurence else we will miss the first occurence, since the search doesn't wrap arround eof anymore.

Note: It would be better to save the state of ws before and then restore it. But that would only matter in a generic version.

Conclusion

Complicated but flexible solution. If you don't need to be flexible, the other vim solutions here are easier (I will not judge other solutions)

like image 38
Doktor OSwaldo Avatar answered Jan 06 '23 05:01

Doktor OSwaldo