This article covers golang sed, go sed, and sed go style workflows: running sed and awk from Go with os/exec. It complements a sed and awk or sed awk tutorial mindset but stays focused on golang execute shell command patterns (argv, stdin, stdout) instead of re-teaching every editor command. For general exec.Command usage, timeouts, and environment, start with How to execute shell commands in Golang.
Examples were run on Linux with GNU
sedandawkavailable on PATH. Behavior can differ on other Unix systems, especially forsed -i.
Golang sed: exec.Command and stdin
To call sed without touching a real project file, pass the script as the first arguments and feed text on stdin:
package main
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
func main() {
cmd := exec.Command("sed", "s/old/NEW/g")
cmd.Stdin = strings.NewReader("hello old world\nsecond old line\n")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
fmt.Println("sed:", err)
return
}
fmt.Print(out.String())
}Run prints both lines with old replaced by NEW.
Golang sed on a short temp file (no -i)
sed can read a path as the last argument and write the transformed stream to stdout, which avoids GNU vs BSD sed -i differences.
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
f, err := os.CreateTemp("", "sed-demo-*.txt")
if err != nil {
fmt.Println(err)
return
}
name := f.Name()
defer os.Remove(name)
fmt.Fprintln(f, "alpha old beta")
fmt.Fprintln(f, "gamma old delta")
f.Close()
out, err := exec.Command("sed", "s/old/NEW/g", name).CombinedOutput()
if err != nil {
fmt.Println(err, string(out))
return
}
fmt.Print(string(out))
}Run shows two lines with old changed to NEW.
More sed awk examples: delete lines and conditional replace
Delete lines that match a pattern (still stdout, no in-place flag):
package main
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
func main() {
cmd := exec.Command("sed", "/remove-me/d")
cmd.Stdin = strings.NewReader("keep\nremove-me\nalso keep\n")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
fmt.Println(err)
return
}
fmt.Print(out.String())
}Run prints only the lines that do not contain remove-me.
Delete a line range from a file you control (here a temp file with six lines):
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
f, err := os.CreateTemp("", "lines-*.txt")
if err != nil {
fmt.Println(err)
return
}
name := f.Name()
defer os.Remove(name)
for i := 1; i <= 6; i++ {
fmt.Fprintf(f, "L%d\n", i)
}
f.Close()
out, err := exec.Command("sed", "2,5d", name).Output()
if err != nil {
fmt.Println(err)
return
}
fmt.Print(string(out))
}Run prints L1 and L6 only.
Replace only on lines that start with a digit:
package main
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
func main() {
cmd := exec.Command("sed", "/^[0-9]/s/foo/BAR/g")
cmd.Stdin = strings.NewReader("9 nine foo foo\nplain foo stays\n")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
fmt.Println(err)
return
}
fmt.Print(out.String())
}Run changes foo on the first line only.
Using awk in golang
Print a column from stdin
package main
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
func main() {
cmd := exec.Command("awk", "{print $2}")
cmd.Stdin = strings.NewReader("col1 col2 col3\nx y z\n")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
fmt.Println(err)
return
}
fmt.Print(out.String())
}Run prints the second field on each line.
Sum a numeric column
package main
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
func main() {
cmd := exec.Command("awk", "{s+=$2} END {print s}")
cmd.Stdin = strings.NewReader("a 1\nb 2\n")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
fmt.Println(err)
return
}
fmt.Print(out.String())
}Run prints 3.
Custom field separator (-F)
For CSV-like input, set -F before the program, as in the awk examples tutorial:
package main
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
func main() {
cmd := exec.Command("awk", "-F,", "{print $2}")
cmd.Stdin = strings.NewReader("a,b,c\n1,2,3\n")
var out bytes.Buffer
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
fmt.Println(err)
return
}
fmt.Print(out.String())
}Run prints b then 2.
Summary
Golang sed and go sed flows use exec.Command("sed", args...) with either stdin or a file path argument, then read stdout instead of relying on sed -i in tutorials where GNU vs BSD breaks readers. The same golang execute shell command pattern applies to awk: set Stdin, capture Stdout, and handle errors without panic in library-style code. For richer command setup, reuse the guidance in golang exec shell commands. When sed awk examples are only string transforms, prefer Go’s regexp or strings for portability; keep sed and awk when their small languages already match your ops scripts.
References
- Package os/exec
- Stack Overflow: calling sed from exec.Command
- Stack Overflow: replace a line in a text file with Go

