spakin/awk

Replace section of a file

OctavioBenedi opened this issue · 1 comments

I'd like to replace the section of a file. Something quite similar to this question on stackoverflow

Following the stackoverflow example, the idea is to replace the section between and (including restApi tags) with another string leaving the other parts of the file unchanged:

....
  <restApi>
    <baseUrl>https://domain.com/nexus</baseUrl>
    <forceBaseUrl>true</forceBaseUrl>
    <uiTimeout>60000</uiTimeout>
  </restApi>
.....

With awk you may execute

awk 'BEGIN {A = 1};/<restApi>/{A=0; print "<sometag>stuff</sometag>"};/.*/ { if ( A == 1) print $0};/<\/restApi>/{A=1}; ' file.xml

I wonder if it's possible to do this with your library?

With Auto or range examples (Examples 15a and 15b) is possible to extract lines between <restApi> and </restApi>, but not the inverse (all lines but the lines within the range), so I haven't find a way to replace those lines without modifying the rest of the file.

Any help or suggestion will be appreciated.

Yes, you can convert the AWK code statement-by-statement to Go:

package main

import (
	"github.com/spakin/awk"
	"os"
)

func main() {
	s := awk.NewScript()

	// BEGIN {A = 1}
	s.Begin = func(s *awk.Script) {
		s.State = true
	}

	// /<restApi>/{A=0; print "<sometag>stuff</sometag>"}
	s.AppendStmt(
		func(s *awk.Script) bool {
			return s.F(0).Match("<restApi>")
		},
		func(s *awk.Script) {
			s.State = false
			s.Println("<sometag>stuff</sometag>")
		})

	// A == 1
	s.AppendStmt(
		func(s *awk.Script) bool {
			return s.State.(bool)
		},
		nil)

	// /<\/restApi>/{A=1}
	s.AppendStmt(
		func(s *awk.Script) bool {
			return s.F(0).Match("</restApi>")
		},
		func(s *awk.Script) {
			s.State = true
		})

	if err := s.Run(os.Stdin); err != nil {
		panic(err)
	}
}

I took the liberty of replacing /.*/ { if ( A == 1) print $0}; with the simpler A == 1. Also, because the program uses only a single variable (A), I stored its value directly in Script.State for convenience. Regular expressions are overkill for comparing against the static strings <restApi> and </restApi>. To more closely match the original, I didn't change these to (faster) string compares, but I'd advise you to do so—in both the AWK and Go versions.