github.com/qjfoidnh/BaiduPCS-Go@v0.0.0-20231011165705-caa18a3765f3/pcsliner/args/args.go (about)

     1  package args
     2  
     3  import (
     4  	"strings"
     5  	"unicode"
     6  )
     7  
     8  const (
     9  	CharEscape      = '\\'
    10  	CharSingleQuote = '\''
    11  	CharDoubleQuote = '"'
    12  	CharBackQuote   = '`'
    13  )
    14  
    15  // IsQuote 是否为引号
    16  func IsQuote(r rune) bool {
    17  	return r == CharSingleQuote || r == CharDoubleQuote || r == CharBackQuote
    18  }
    19  
    20  // Parse 解析line, 忽略括号
    21  func Parse(line string) (lineArgs []string) {
    22  	var (
    23  		rl        = []rune(line + " ")
    24  		buf       = strings.Builder{}
    25  		quoteChar rune
    26  		nextChar  rune
    27  		escaped   bool
    28  		in        bool
    29  	)
    30  
    31  	var (
    32  		isSpace bool
    33  	)
    34  
    35  	for k, r := range rl {
    36  		isSpace = unicode.IsSpace(r)
    37  		if !isSpace && !in {
    38  			in = true
    39  		}
    40  
    41  		switch {
    42  		case escaped: // 已转义, 跳过
    43  			escaped = false
    44  			//pass
    45  		case r == CharEscape: // 转义模式
    46  			if k+1+1 < len(rl) { // 不是最后一个字符, 多+1是因为最后一个空格
    47  				nextChar = rl[k+1]
    48  				// 仅支持转义这些字符, 否则原样输出反斜杠
    49  				if unicode.IsSpace(nextChar) || IsQuote(nextChar) || nextChar == CharEscape {
    50  					escaped = true
    51  					continue
    52  				}
    53  			}
    54  			// pass
    55  		case IsQuote(r):
    56  			if quoteChar == 0 { //未引
    57  				quoteChar = r
    58  				continue
    59  			}
    60  
    61  			if quoteChar == r { //取消引
    62  				quoteChar = 0
    63  				continue
    64  			}
    65  		case isSpace:
    66  			if !in { // 忽略多余的空格
    67  				continue
    68  			}
    69  			if quoteChar == 0 { // 未在引号内
    70  				lineArgs = append(lineArgs, buf.String())
    71  				buf.Reset()
    72  				in = false
    73  				continue
    74  			}
    75  		}
    76  
    77  		buf.WriteRune(r)
    78  	}
    79  
    80  	return
    81  }