Search code examples
vimsed

Scripting with vim/sed to delete variable and replace it with several new lines above


I have this pattern in a file

~> more file.f
   c     %-------------------------------%
         integer*4 ierr, comm, myid, nprocs, cnprocs, color
         call MPI_INIT( ierr )

I need to delete comm and replace it with several lines at the top of it. For now, from a bash prompt (this will need to be scripted in a bash script in the end), I tried:

   vim -c "%g/      integer.\+comm/norm O" -c "x" file.f
   vim -c "%g/      integer.\+comm/norm k0s#ifdef HAVE_MPI_ICB\\r      type(MPI_Comm) comm\\r#else\\r          integer*4 comm\\r#endif\\r" -c "x" file.f

First vim -c is for creating a new line above. Second vim -c is for writting this new line using normal mode (would like to do this in one shot - didn't succeed for now!). I get (+ sign below is output of git-diff)

  c     %-------------------------------%
 +#ifdef HAVE_MPI_ICB\r      type(MPI_Comm) comm\r#else\r      integer*4 comm\r#endif\r
        integer*4 ierr, comm, myid, nprocs, cnprocs, color

... Which is not what I need. Ideally, I need to get:

  c     %-------------------------------%
 +#ifdef HAVE_MPI_ICB
 +      type(MPI_Comm) comm
 +#else
 +      integer*4 comm
 +#endif
        integer*4 ierr, myid, nprocs, cnprocs, color

comm need to be deleted on the initial line and be replaced with the lines added above.

No clue how to get that. Can somebody help?

EDIT

I actually have 3 patterns to handle in the same file in different fortran subroutine (comm can come first or after the first variable)

  integer*4 ierr, comm, myid, nprocs, cnprocs, color
  integer*4         comm, myid, nprocs, rc, ierr
  integer*4         comm, nprocs, myid, ierr,

EDIT

Solution that works

sed -i.orig '/\(integer.*\)[[:blank:]]*comm, /{
s//\1/
i\
+#ifdef HAVE_MPI_ICB\
+      type(MPI_Comm) comm\
+#else\
+      integer*4 comm\
+#endif
}' file.f

Solution

  • I'm not familiar with vi scripting but a sed command would be:

    sed -i.orig '/\(integer.*[[:blank:],]\)comm[[:blank:]]*,/{
    s//\1/
    i\
    +#ifdef HAVE_MPI_ICB\
    +      type(MPI_Comm) comm\
    +#else\
    +      integer*4 comm\
    +#endif
    }' file.f
    

    Note: This won't work if the comm isn't followed by a , in the line.