Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ Filters are methods on an existing pipe that also return a pipe, allowing you to
| [`SHA256Sums`](https://pkg.go.dev/github.com/bitfield/script#Pipe.SHA256Sums) | SHA-256 hashes of each listed file |
| [`Tee`](https://pkg.go.dev/github.com/bitfield/script#Pipe.Tee) | input copied to supplied writers |

Note that filters run concurrently, rather than producing nothing until each stage has fully read its input. This is convenient for executing long-running comands, for example. If you do need to wait for the pipeline to complete, call [`Wait`](https://pkg.go.dev/github.com/bitfield/script#Pipe.Wait).
Note that filters run concurrently, rather than producing nothing until each stage has fully read its input. This is convenient for executing long-running commands, for example. If you do need to wait for the pipeline to complete, call [`Wait`](https://pkg.go.dev/github.com/bitfield/script#Pipe.Wait).

## Sinks

Expand Down
34 changes: 34 additions & 0 deletions script.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,20 @@ func (p *Pipe) FilterScan(filter func(string, io.Writer)) *Pipe {
})
}

// FilterScanTrackLine behaves the same way as FilterScan() but also returns the
// line number of the processed input
func (p *Pipe) FilterScanTrackLine(filter func(string, io.Writer, int)) *Pipe {
return p.Filter(func(r io.Reader, w io.Writer) error {
scanner := newScanner(r)
line := 1
for scanner.Scan() {
filter(scanner.Text(), w, line)
line++
}
return scanner.Err()
})
}

// First produces only the first n lines of the pipe's contents, or all the
// lines if there are less than n. If n is zero or negative, there is no output
// at all.
Expand Down Expand Up @@ -684,6 +698,16 @@ func (p *Pipe) Match(s string) *Pipe {
})
}

// MatchWithLineNumber behaves the same way as Match() but concatenates the
// line number the pattern was found in (similar to `grep -n`)
func (p *Pipe) MatchWithLineNumber(s string) *Pipe {
return p.FilterScanTrackLine(func(line string, w io.Writer, lineNumber int) {
if strings.Contains(line, s) {
fmt.Fprintln(w, fmt.Sprint(lineNumber)+":"+line)
}
})
}

// MatchRegexp produces only the input lines that match the compiled regexp re.
func (p *Pipe) MatchRegexp(re *regexp.Regexp) *Pipe {
return p.FilterScan(func(line string, w io.Writer) {
Expand All @@ -693,6 +717,16 @@ func (p *Pipe) MatchRegexp(re *regexp.Regexp) *Pipe {
})
}

// MatchRegexpWithLineNumber behaves the same way as MatchRegexp but concatenates the
// line number the pattern was found in (similar to `grep -n`)
func (p *Pipe) MatchRegexpWithLineNumber(re *regexp.Regexp) *Pipe {
return p.FilterScanTrackLine(func(line string, w io.Writer, lineNumber int) {
if re.MatchString(line) {
fmt.Fprintln(w, fmt.Sprint(lineNumber)+":"+line)
}
})
}

// Post makes an HTTP POST request to url, using the contents of the pipe as
// the request body, and produces the server's response. See [Pipe.Do] for how
// the HTTP response status is interpreted.
Expand Down
Loading