/
utilsplit.go
61 lines (57 loc) · 1.56 KB
/
utilsplit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// Copyright 2020 The play-with-go.dev Authors. All rights reserved. Use of
// this source code is governed by a BSD-style license that can be found in the
// LICENSE file.
package main
import (
"fmt"
"strconv"
"strings"
)
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// split breaks the line into words
func split(line string) ([]string, error) {
// Parse line, obeying quoted strings.
var words []string
// One (possibly quoted) word per iteration.
Words:
for {
line = strings.TrimLeft(line, " \t")
if len(line) == 0 {
break
}
if line[0] == '"' {
for i := 1; i < len(line); i++ {
c := line[i] // Only looking for ASCII so this is OK.
switch c {
case '\\':
if i+1 == len(line) {
return nil, fmt.Errorf("bad backslash")
}
i++ // Absorb next byte (If it's a multibyte we'll get an error in Unquote).
case '"':
word, err := strconv.Unquote(line[0 : i+1])
if err != nil {
return nil, fmt.Errorf("bad quoted string")
}
words = append(words, word)
line = line[i+1:]
// Check the next character is space or end of line.
if len(line) > 0 && line[0] != ' ' && line[0] != '\t' {
return nil, fmt.Errorf("expect space after quoted argument")
}
continue Words
}
}
return nil, fmt.Errorf("mismatched quoted string")
}
i := strings.IndexAny(line, " \t")
if i < 0 {
i = len(line)
}
words = append(words, line[0:i])
line = line[i:]
}
return words, nil
}