file/edit.go
func (e *edit) genReplaceAtLine(r []ReplacerAtLine, n int) error {
	if n == 0 {
		return nil
	}
	if _, err := e.file.Seek(0, os.SEEK_SET); err != nil {
		return err
	}

	// == Cache the regular expressions
	allReLine := make([]*regexp.Regexp, len(r))
	allReSearch := make([]*regexp.Regexp, len(r))
	allRepl := make([][]byte, len(r))

	for i, v := range r {
		if reLine, err := regexp.Compile(v.Line); err != nil {
			return err
		} else {
			allReLine[i] = reLine
		}

		if reSearch, err := regexp.Compile(v.Search); err != nil {
			return err
		} else {
			allReSearch[i] = reSearch
		}

		allRepl[i] = []byte(v.Replace)
	}

	buf := new(bytes.Buffer)
	isNew := false

	// Replace every line, if it maches
	for {
		line, err := e.buf.ReadBytes('\n')
		if err == io.EOF {
			break
		}

		for i, _ := range r {
			if allReLine[i].Match(line) {
				j := n

				line = allReSearch[i].ReplaceAllFunc(line, func(s []byte) []byte {
					if !isNew {
						isNew = true
					}

					if j != 0 {
						j--
						return allRepl[i]
					}
					return s
				})
			}
		}
		if _, err = buf.Write(line); err != nil {
			return err
		}
	}

	if isNew {
		return e.rewrite(buf.Bytes())
	}
	return nil
}
func (e *edit) genReplaceAtLine(r []ReplacerAtLine, n int) error {
	if n == 0 {
		return nil
	}
	if _, err := e.file.Seek(0, os.SEEK_SET); err != nil {
		return err
	}

	// == Cache the regular expressions
	allReLine := make([]*regexp.Regexp, len(r))
	allReSearch := make([]*regexp.Regexp, len(r))
	allRepl := make([][]byte, len(r))

	for i, v := range r {
		if reLine, err := regexp.Compile(v.Line); err != nil {
			return err
		} else {
			allReLine[i] = reLine
		}

		if reSearch, err := regexp.Compile(v.Search); err != nil {
			return err
		} else {
			allReSearch[i] = reSearch
		}

		allRepl[i] = []byte(v.Replace)
	}

	buf := new(bytes.Buffer)
	isNew := false

	// Replace every line, if it maches
	for {
		line, err := e.buf.ReadBytes('\n')
		if err == io.EOF {
			break
		}

		for i, _ := range r {
			if allReLine[i].Match(line) {
				j := n

				line = allReSearch[i].ReplaceAllFunc(line, func(s []byte) []byte {
					if !isNew {
						isNew = true
					}

					if j != 0 {
						j--
						return allRepl[i]
					}
					return s
				})
			}
		}
		if _, err = buf.Write(line); err != nil {
			return err
		}
	}

	if isNew {
		return e.rewrite(buf.Bytes())
	}
	return nil
}
// Generic ReplaceAtLine: replaces a number of regular expressions matched in r,
// if the line is matched at the first.