Advertisement
Guest User

Untitled

a guest
Jun 22nd, 2017
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 1.93 KB | None | 0 0
  1. /*
  2. Try:
  3.  
  4. cat | go run rxstream.go '(?ms)(.*)42' '{"chars before 42": "$1"}'
  5.  
  6. And input:
  7.  
  8. abc42abc42
  9.  
  10. */
  11. package main
  12.  
  13. import (
  14. "io"
  15. "os"
  16. "regexp"
  17. )
  18.  
  19. // replace with pattern
  20. // returns the number of matches
  21. func streamReplaceRx(
  22. w io.Writer,
  23. r io.Reader,
  24. rx *regexp.Regexp,
  25. replacement []byte,
  26. readBuf []byte,
  27. ) (int, error) {
  28. var (
  29. matchCount int
  30. matchBuf []byte
  31. eof bool
  32. )
  33.  
  34. readLoop:
  35. for {
  36. if eof {
  37. // output the remaining buffer
  38. _, err := w.Write(matchBuf)
  39. return matchCount, err
  40. }
  41.  
  42. n, err := r.Read(readBuf)
  43. if err != nil {
  44. if err == io.EOF {
  45. // depending on the reader implementation, we cannot be sure if any bytes were
  46. // read, so we need to do a matching round before returning
  47. eof = true
  48. err = nil
  49. } else {
  50. return matchCount, err
  51. }
  52. }
  53.  
  54. // store what was read
  55. matchBuf = append(matchBuf, readBuf[:n]...)
  56.  
  57. // find all the matches in the currently available input
  58. for {
  59. // find the next match, with submatches for template replacement
  60. m := rx.FindSubmatchIndex(matchBuf)
  61.  
  62. // if there is no match, we need to read more, because we don't know if the expression
  63. // could match a longer input
  64. if len(m) == 0 {
  65. continue readLoop
  66. }
  67.  
  68. matchCount++
  69.  
  70. // the unmatched part of the input
  71. if _, err := w.Write(matchBuf[:m[0]]); err != nil {
  72. return matchCount, err
  73. }
  74.  
  75. // avoid looping around zero-length matches by reading more
  76. if m[0] == m[1] {
  77. continue readLoop
  78. }
  79.  
  80. // the replacement
  81. if _, err := w.Write(rx.Expand(nil, replacement, matchBuf, m)); err != nil {
  82. return matchCount, err
  83. }
  84.  
  85. // remove until the matched part and continue checking for matches in the available
  86. // input
  87. matchBuf = matchBuf[m[1]:]
  88. }
  89. }
  90. }
  91.  
  92. func main() {
  93. if len(os.Args) < 3 {
  94. os.Exit(2)
  95. }
  96.  
  97. rx := regexp.MustCompile(os.Args[1])
  98.  
  99. readBuf := make([]byte, 4)
  100. streamReplaceRx(
  101. os.Stdout,
  102. os.Stdin,
  103. rx,
  104. []byte(os.Args[2]),
  105. readBuf,
  106. )
  107. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement