Skip to content

Commit

Permalink
script: Implement simple "sed" command
Browse files Browse the repository at this point in the history
The simple 'replace' command falls short in situations
where the input text isn't fully known, but still needs
to be sanitized in some way. Instead of having to use e.g.
the system 'sed' command, implement a very simple built-in
version.

Signed-off-by: Jussi Maki <[email protected]>
  • Loading branch information
joamaki committed Dec 13, 2024
1 parent d02f07f commit 553aca4
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
40 changes: 40 additions & 0 deletions script/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func DefaultCmds() map[string]Cmd {
"mv": Mv(),
"rm": Rm(),
"replace": Replace(),
"sed": Sed(),
"sleep": Sleep(),
"stderr": Stderr(),
"stdout": Stdout(),
Expand Down Expand Up @@ -882,6 +883,45 @@ func Replace() Cmd {
})
}

// Sed implements a simple regexp replacement of text in a file.
func Sed() Cmd {
return Command(
CmdUsage{
Summary: "substitute strings in a file with a regexp",
Args: "regexp replacement file",
Detail: []string{
"A simple sed-like command for replacing text matching regular expressions",
"in a file.",
"",
"Implemented using regexp.ReplaceAll, see its docs for what is supported:",
"https://pkg.go.dev/regexp#Regexp.ReplaceAll",
},
RegexpArgs: firstNonFlag,
},
func(s *State, args ...string) (WaitFunc, error) {
if len(args) != 3 {
return nil, ErrUsage
}

re, err := regexp.Compile(args[0])
if err != nil {
return nil, err
}
replacement := args[1]
file := s.Path(args[2])

data, err := os.ReadFile(file)
if err != nil {
return nil, err
}
lines := strings.Split(string(data), "\n")
for i, line := range lines {
lines[i] = re.ReplaceAllString(line, replacement)
}
return nil, os.WriteFile(file, []byte(strings.Join(lines, "\n")), 0666)
})
}

// Rm removes a file or directory.
//
// If a directory, Rm also recursively removes that directory's
Expand Down
20 changes: 20 additions & 0 deletions script/scripttest/testdata/sed.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Tests for the sed command

sed '' '' input.txt
sed notfound unexpected input.txt
sed \d+ N input.txt
sed [uz] '' input.txt
sed a(x*)b 'a${1}c' input.txt
sed ^(s+)$ '${1}${1}' input.txt
cmp input.txt expected.txt

-- input.txt --
foo123bar
quuxbaz123
axxxxxxb
sss
-- expected.txt --
fooNbar
qxbaN
axxxxxxc
ssssss

0 comments on commit 553aca4

Please sign in to comment.