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 62
|
// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0
package execplugin
import (
"fmt"
"strings"
"unicode"
)
// ShlexSplit splits a string into a slice of strings using shell-style rules for quoting and commenting
// Similar to Python's shlex.split with comments enabled
func ShlexSplit(s string) ([]string, error) {
return shlexSplit(s)
}
func shlexSplit(s string) ([]string, error) {
result := []string{}
// noQuote is used to track if we are not in a quoted
const noQuote = 0
var current strings.Builder
var quote rune = noQuote
var escaped bool
for _, r := range s {
switch {
case escaped:
current.WriteRune(r)
escaped = false
case r == '\\' && quote != '\'':
escaped = true
case (r == '\'' || r == '"') && quote == noQuote:
quote = r
case r == quote:
quote = noQuote
case r == '#' && quote == noQuote:
// Comment starts, ignore the rest of the line
if current.Len() > 0 {
result = append(result, current.String())
}
return result, nil
case unicode.IsSpace(r) && quote == noQuote:
if current.Len() > 0 {
result = append(result, current.String())
current.Reset()
}
default:
current.WriteRune(r)
}
}
if quote != noQuote {
return nil, fmt.Errorf("unclosed quote in string")
}
if current.Len() > 0 {
result = append(result, current.String())
}
return result, nil
}
|