You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ntool/nstr/split.go

160 lines
3.9 KiB
Go

1 year ago
package nstr
import "strings"
/*************************************************************
* String split operation
*************************************************************/
// Cut same of the strings.Cut
func Cut(s, sep string) (before string, after string, found bool) {
if i := strings.Index(s, sep); i >= 0 {
return s[:i], s[i+len(sep):], true
}
return s, "", false
}
// QuietCut always returns two substring.
func QuietCut(s, sep string) (before string, after string) {
before, after, _ = Cut(s, sep)
return
}
// MustCut always returns two substring.
func MustCut(s, sep string) (before string, after string) {
var ok bool
before, after, ok = Cut(s, sep)
if !ok {
panic("cannot split input string to two nodes")
}
return
}
// TrimCut always returns two substring and trim space for items.
func TrimCut(s, sep string) (string, string) {
before, after, _ := Cut(s, sep)
return strings.TrimSpace(before), strings.TrimSpace(after)
}
// SplitKV split string to key and value.
func SplitKV(s, sep string) (string, string) { return TrimCut(s, sep) }
// SplitValid string to slice. will trim each item and filter empty string node.
func SplitValid(s, sep string) (ss []string) { return Split(s, sep) }
// Split string to slice. will trim each item and filter empty string node.
func Split(s, sep string) (ss []string) {
if s = strings.TrimSpace(s); s == "" {
return
}
for _, val := range strings.Split(s, sep) {
if val = strings.TrimSpace(val); val != "" {
ss = append(ss, val)
}
}
return
}
// SplitNValid string to slice. will filter empty string node.
func SplitNValid(s, sep string, n int) (ss []string) { return SplitN(s, sep, n) }
// SplitN string to slice. will filter empty string node.
func SplitN(s, sep string, n int) (ss []string) {
if s = strings.TrimSpace(s); s == "" {
return
}
rawList := strings.Split(s, sep)
for i, val := range rawList {
if val = strings.TrimSpace(val); val != "" {
if len(ss) == n-1 {
ss = append(ss, strings.TrimSpace(strings.Join(rawList[i:], sep)))
break
}
ss = append(ss, val)
}
}
return
}
// SplitTrimmed split string to slice.
// will trim space for each node, but not filter empty
func SplitTrimmed(s, sep string) (ss []string) {
if s = strings.TrimSpace(s); s == "" {
return
}
for _, val := range strings.Split(s, sep) {
ss = append(ss, strings.TrimSpace(val))
}
return
}
// SplitNTrimmed split string to slice.
// will trim space for each node, but not filter empty
func SplitNTrimmed(s, sep string, n int) (ss []string) {
if s = strings.TrimSpace(s); s == "" {
return
}
for _, val := range strings.SplitN(s, sep, n) {
ss = append(ss, strings.TrimSpace(val))
}
return
}
// Substring returns a substring of the specified length starting at the specified offset position.
// if length <= 0, return pos to end.
func Substring(s string, pos, length int) string {
runes := []rune(s)
strLn := len(runes)
// pos is too large
if pos >= strLn {
return ""
}
stopIdx := pos + length
if length == 0 || stopIdx > strLn {
stopIdx = strLn
} else if length < 0 {
stopIdx = strLn + length
}
return string(runes[pos:stopIdx])
}
// SplitInlineComment for an inline text string.
func SplitInlineComment(val string, strict ...bool) (string, string) {
// strict check: must with space
if len(strict) > 0 && strict[0] {
if pos := strings.Index(val, " #"); pos > -1 {
return strings.TrimRight(val[0:pos], " "), val[pos+1:]
}
if pos := strings.Index(val, " //"); pos > -1 {
return strings.TrimRight(val[0:pos], " "), val[pos+1:]
}
} else {
if pos := strings.IndexByte(val, '#'); pos > -1 {
return strings.TrimRight(val[0:pos], " "), val[pos:]
}
if pos := strings.Index(val, "//"); pos > -1 {
return strings.TrimRight(val[0:pos], " "), val[pos:]
}
}
return val, ""
}
// FirstLine from command output
func FirstLine(output string) string {
if i := strings.IndexByte(output, '\n'); i >= 0 {
return output[0:i]
}
return output
}