mirror of https://github.com/shunfei/cronsun
support complex arguments
parent
4fec80c187
commit
a75dac0988
11
job.go
11
job.go
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/shunfei/cronsun/conf"
|
"github.com/shunfei/cronsun/conf"
|
||||||
"github.com/shunfei/cronsun/log"
|
"github.com/shunfei/cronsun/log"
|
||||||
"github.com/shunfei/cronsun/node/cron"
|
"github.com/shunfei/cronsun/node/cron"
|
||||||
|
"github.com/shunfei/cronsun/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -387,7 +388,15 @@ func (j *Job) alone() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Job) splitCmd() {
|
func (j *Job) splitCmd() {
|
||||||
j.cmd = strings.Split(j.Command, " ")
|
ps := strings.SplitN(j.Command, " ", 2)
|
||||||
|
if len(ps) == 1 {
|
||||||
|
j.cmd = ps
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
j.cmd = make([]string, 0, 2)
|
||||||
|
j.cmd = append(j.cmd, ps[0])
|
||||||
|
j.cmd = append(j.cmd, utils.ParseCmdArguments(ps[1])...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Job) String() string {
|
func (j *Job) String() string {
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fmsState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
stateArgumentOutside fmsState = iota
|
||||||
|
stateArgumentStart
|
||||||
|
stateArgumentEnd
|
||||||
|
)
|
||||||
|
|
||||||
|
var errEndOfLine = errors.New("End of line")
|
||||||
|
|
||||||
|
type cmdArgumentParser struct {
|
||||||
|
s string
|
||||||
|
i int
|
||||||
|
length int
|
||||||
|
state fmsState
|
||||||
|
startToken byte
|
||||||
|
shouldEscape bool
|
||||||
|
currArgument []byte
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCmdArgumentParser(s string) *cmdArgumentParser {
|
||||||
|
return &cmdArgumentParser{
|
||||||
|
s: s,
|
||||||
|
i: -1,
|
||||||
|
length: len(s),
|
||||||
|
currArgument: make([]byte, 0, 16),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cap *cmdArgumentParser) parse() (arguments []string) {
|
||||||
|
for {
|
||||||
|
cap.next()
|
||||||
|
|
||||||
|
if cap.err != nil {
|
||||||
|
if cap.shouldEscape {
|
||||||
|
cap.currArgument = append(cap.currArgument, '\\')
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cap.currArgument) > 0 {
|
||||||
|
arguments = append(arguments, string(cap.currArgument))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch cap.state {
|
||||||
|
case stateArgumentOutside:
|
||||||
|
cap.detectStartToken()
|
||||||
|
case stateArgumentStart:
|
||||||
|
if !cap.detectEnd() {
|
||||||
|
cap.detectContent()
|
||||||
|
}
|
||||||
|
case stateArgumentEnd:
|
||||||
|
cap.state = stateArgumentOutside
|
||||||
|
arguments = append(arguments, string(cap.currArgument))
|
||||||
|
cap.currArgument = cap.currArgument[:0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cap *cmdArgumentParser) previous() {
|
||||||
|
if cap.i >= 0 {
|
||||||
|
cap.i--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cap *cmdArgumentParser) next() {
|
||||||
|
if cap.length-cap.i == 1 {
|
||||||
|
cap.err = errEndOfLine
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cap.i++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cap *cmdArgumentParser) detectStartToken() {
|
||||||
|
c := cap.s[cap.i]
|
||||||
|
if c == ' ' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c {
|
||||||
|
case '\\':
|
||||||
|
cap.startToken = 0
|
||||||
|
cap.shouldEscape = true
|
||||||
|
//cap.currArgument = append(cap.currArgument, c)
|
||||||
|
case '"', '\'':
|
||||||
|
cap.startToken = c
|
||||||
|
//cap.currArgument = append(cap.currArgument, c)
|
||||||
|
default:
|
||||||
|
cap.startToken = 0
|
||||||
|
cap.previous()
|
||||||
|
}
|
||||||
|
cap.state = stateArgumentStart
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cap *cmdArgumentParser) detectContent() {
|
||||||
|
c := cap.s[cap.i]
|
||||||
|
|
||||||
|
if cap.shouldEscape {
|
||||||
|
switch c {
|
||||||
|
case ' ', '\\', cap.startToken:
|
||||||
|
cap.currArgument = append(cap.currArgument, c)
|
||||||
|
default:
|
||||||
|
cap.currArgument = append(cap.currArgument, '\\', c)
|
||||||
|
}
|
||||||
|
cap.shouldEscape = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == '\\' {
|
||||||
|
cap.shouldEscape = true
|
||||||
|
} else {
|
||||||
|
cap.currArgument = append(cap.currArgument, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cap *cmdArgumentParser) detectEnd() (detected bool) {
|
||||||
|
c := cap.s[cap.i]
|
||||||
|
|
||||||
|
if cap.startToken == 0 {
|
||||||
|
if c == ' ' && !cap.shouldEscape {
|
||||||
|
cap.state = stateArgumentEnd
|
||||||
|
cap.previous()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if c == cap.startToken && !cap.shouldEscape {
|
||||||
|
//cap.currArgument = append(cap.currArgument, c)
|
||||||
|
cap.state = stateArgumentEnd
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseCmdArguments(s string) (arguments []string) {
|
||||||
|
return newCmdArgumentParser(s).parse()
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCmdArgumentParser(t *testing.T) {
|
||||||
|
var args []string
|
||||||
|
var str string
|
||||||
|
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
str = " "
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
str = "aa bbb ccc "
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 3)
|
||||||
|
So(args[0], ShouldEqual, "aa")
|
||||||
|
So(args[1], ShouldEqual, "bbb")
|
||||||
|
So(args[2], ShouldEqual, "ccc")
|
||||||
|
})
|
||||||
|
|
||||||
|
str = "' \\\""
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 1)
|
||||||
|
So(args[0], ShouldEqual, " \\\"")
|
||||||
|
})
|
||||||
|
|
||||||
|
str = `a "b c"` // a "b c"
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 2)
|
||||||
|
So(args[0], ShouldEqual, "a")
|
||||||
|
So(args[1], ShouldEqual, "b c")
|
||||||
|
})
|
||||||
|
|
||||||
|
str = `a '\''"`
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 2)
|
||||||
|
So(args[0], ShouldEqual, "a")
|
||||||
|
So(args[1], ShouldEqual, "'")
|
||||||
|
})
|
||||||
|
|
||||||
|
str = ` \\a 'b c' c\ d\ `
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 3)
|
||||||
|
So(args[0], ShouldEqual, "\\a")
|
||||||
|
So(args[1], ShouldEqual, "b c")
|
||||||
|
So(args[2], ShouldEqual, "c d ")
|
||||||
|
})
|
||||||
|
|
||||||
|
str = `\`
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 1)
|
||||||
|
So(args[0], ShouldEqual, "\\")
|
||||||
|
})
|
||||||
|
|
||||||
|
str = ` \ ` // \SPACE
|
||||||
|
Convey("Parse Cmd Arguments ["+str+"]", t, func() {
|
||||||
|
args = ParseCmdArguments(str)
|
||||||
|
So(len(args), ShouldEqual, 1)
|
||||||
|
So(args[0], ShouldEqual, " ")
|
||||||
|
})
|
||||||
|
}
|
Loading…
Reference in New Issue