-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprogram.go
More file actions
101 lines (88 loc) · 2.99 KB
/
Copy pathprogram.go
File metadata and controls
101 lines (88 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package command
import (
"fmt"
"strings"
)
// Context provides access to awk's execution context for each line. It is an
// immutable value: the Set… methods return an updated copy rather than
// mutating in place, and programs hand the updated context back to the
// pipeline (Begin and Action return it).
type Context struct {
Variables map[string]any
FS string
OFS string
RS string
Fields []string
NR int64
NF int
}
// Field returns the field at the given index (0 = whole line, 1 = first field, etc.)
func (c Context) Field(index int) string {
if index < 0 || index >= len(c.Fields) {
return ""
}
return c.Fields[index]
}
// SetField returns a copy of the context with the field at index set, growing
// the record as needed. A negative index returns the context unchanged.
func (c Context) SetField(index int, value string) Context {
if index < 0 {
return c
}
fields := make([]string, max(len(c.Fields), index+1))
copy(fields, c.Fields)
fields[index] = value
c.Fields = fields
c.NF = len(fields) - 1 // Don't count $0
return c
}
// Var returns a variable value
func (c Context) Var(name string) any {
if c.Variables == nil {
return nil
}
return c.Variables[name]
}
// SetVar returns a copy of the context with the variable set.
func (c Context) SetVar(name string, value any) Context {
vars := make(map[string]any, len(c.Variables)+1)
for k, v := range c.Variables {
vars[k] = v
}
vars[name] = value
c.Variables = vars
return c
}
// Print formats and returns a string with fields separated by OFS
func (c Context) Print(values ...any) string {
parts := make([]string, len(values))
for i, v := range values {
parts[i] = fmt.Sprint(v)
}
return strings.Join(parts, c.OFS)
}
// Program defines the interface for awk-style programs
// all methods are optional - implement only what you need
type Program interface {
// Begin is called once before processing any lines
// Use this for initialization; return the (possibly updated) context
Begin(ctx Context) (Context, error)
// Condition is called for each line to determine if Action should run
// Return true to run the action, false to skip
Condition(ctx Context) bool
// Action is called for each line where Condition returns true
// Return the updated context, the output string, and whether to emit it
Action(ctx Context) (updated Context, output string, isEmit bool)
// End is called once after processing all lines
// Return any final output and an error if needed
End(ctx Context) (output string, err error)
}
// SimpleProgram provides default implementations for all Program methods
// Embed this in your program struct and override only what you need
type SimpleProgram struct{}
func (SimpleProgram) Begin(ctx Context) (Context, error) { return ctx, nil }
func (SimpleProgram) Condition(Context) bool { return true }
func (SimpleProgram) Action(ctx Context) (Context, string, bool) {
return ctx, ctx.Field(0), true
}
func (SimpleProgram) End(Context) (string, error) { return "", nil }