Skip to content

Commit 753a232

Browse files
committed
Add Position to detect remaining words
This should be useful to detect the line has multiple-commands, redirect or etc, like below. foo; bar foo && bar foo || bar foo < file foo > file
1 parent 33bd8f1 commit 753a232

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

shellwords.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ func replaceEnv(s string) string {
3434
type Parser struct {
3535
ParseEnv bool
3636
ParseBacktick bool
37+
Position int
3738
}
3839

3940
func NewParser() *Parser {
40-
return &Parser{ParseEnv, ParseBacktick}
41+
return &Parser{ParseEnv, ParseBacktick, 0}
4142
}
4243

4344
func (p *Parser) Parse(line string) ([]string, error) {
@@ -46,7 +47,10 @@ func (p *Parser) Parse(line string) ([]string, error) {
4647
var escaped, doubleQuoted, singleQuoted, backQuote bool
4748
backtick := ""
4849

49-
for _, r := range line {
50+
pos := -1
51+
52+
loop:
53+
for i, r := range line {
5054
if escaped {
5155
buf += string(r)
5256
escaped = false
@@ -104,6 +108,11 @@ func (p *Parser) Parse(line string) ([]string, error) {
104108
singleQuoted = !singleQuoted
105109
continue
106110
}
111+
case ';', '&', '|', '<', '>':
112+
if !(escaped || singleQuoted || doubleQuoted || backQuote) {
113+
pos = i
114+
break loop
115+
}
107116
}
108117

109118
buf += string(r)
@@ -123,6 +132,8 @@ func (p *Parser) Parse(line string) ([]string, error) {
123132
return nil, errors.New("invalid command line string")
124133
}
125134

135+
p.Position = pos
136+
126137
return args, nil
127138
}
128139

shellwords_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,36 @@ func TestDupEnv(t *testing.T) {
146146
t.Fatalf("Expected %v, but %v:", expected, args)
147147
}
148148
}
149+
150+
func TestHaveMore(t *testing.T) {
151+
parser := NewParser()
152+
parser.ParseEnv = true
153+
154+
line := "echo foo; seq 1 10"
155+
args, err := parser.Parse(line)
156+
if err != nil {
157+
t.Fatalf(err.Error())
158+
}
159+
expected := []string{"echo", "foo"}
160+
if !reflect.DeepEqual(args, expected) {
161+
t.Fatalf("Expected %v, but %v:", expected, args)
162+
}
163+
164+
if parser.Position == 0 {
165+
t.Fatalf("Commands should be remaining")
166+
}
167+
168+
line = string([]rune(line)[parser.Position+1:])
169+
args, err = parser.Parse(line)
170+
if err != nil {
171+
t.Fatalf(err.Error())
172+
}
173+
expected = []string{"seq", "1", "10"}
174+
if !reflect.DeepEqual(args, expected) {
175+
t.Fatalf("Expected %v, but %v:", expected, args)
176+
}
177+
178+
if parser.Position > 0 {
179+
t.Fatalf("Commands should not be remaining")
180+
}
181+
}

0 commit comments

Comments
 (0)