Golang sed and awk examples from Go with os/exec

Golang sed and go sed: call sed and awk from Go with os/exec, stdin pipes, temp files, and notes on in-place edits and golang execute shell command patterns.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

Golang sed and awk examples from Go with os/exec

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 sed and awk available on PATH. Behavior can differ on other Unix systems, especially for sed -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:

go
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())
}
Output

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.

go
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))
}
Output

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):

go
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())
}
Output

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):

go
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))
}
Output

Run prints L1 and L6 only.

Replace only on lines that start with a digit:

go
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())
}
Output

Run changes foo on the first line only.


Using awk in golang

go
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())
}
Output

Run prints the second field on each line.

Sum a numeric column

go
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())
}
Output

Run prints 3.

Custom field separator (-F)

For CSV-like input, set -F before the program, as in the awk examples tutorial:

go
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())
}
Output

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


Frequently Asked Questions

1. Should I use cmd.Output or cmd.Run for sed and awk?

Use Output when you only need stdout as a byte slice. Use Run when you set Stdout and Stderr yourself, stream large data, or need separate error text from stderr.

2. Why avoid sed -i in examples?

In-place flags differ between GNU and BSD sed, and silently mutating paths is risky in samples. Prefer sed without -i and capture stdout, or manage a temp file explicitly in Go.

3. Is exec.Command the same as “shelling out”?

exec.Command builds argv without invoking a shell unless you call sh -c with a single string, which is harder to quote safely.

4. When should I skip sed or awk entirely?

For simple string work, regexp and bytes/strings in Go are portable. Reach for sed or awk when you already rely on their idioms or pipeline with existing scripts.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …