当我分割字符串时,如何在输出中包含运算符?

时间:2015-06-04 00:44:35

标签: regex go

昨天我问this question有关在python中拆分字符串的问题。我决定在Go做这个项目。我有以下内容:

input := "house-width + 3 - y ^ (5 * house length)"
s := regexp.MustCompile(" ([+-/*^]) ").Split(input, -1)
log.Println(s)  //  [house-width 3 y (5 house length)]

如何在此输出中包含运算符?例如我想要以下输出:

['house-width', '+', '3', '-', 'y', '^', '(5', '*', 'house length)']

编辑: 为了澄清我在分隔空间的操作员而不仅仅是操作员。操作员必须在两端都有一个空格,以区别于短划线/连字符。如果需要,请参考我链接到的原始python问题以进行说明。

3 个答案:

答案 0 :(得分:1)

您可以使用regexp.Split()获取表达式的操作数(就像您一样),您可以使用regexp.FindAllString()获取运算符(分隔符)。

通过执行此操作,您将拥有2个单独的[]string切片,如果您希望将结果放在一个[]string切片中,则可以合并这两个切片。

input := "house-width + 3 - y ^ (5 * house length)"

r := regexp.MustCompile(`\s([+\-/*^])\s`)

s1 := r.Split(input, -1)
s2 := r.FindAllString(input, -1)

fmt.Printf("%q\n", s1)
fmt.Printf("%q\n", s2)

all := make([]string, len(s1)+len(s2))
for i := range s1 {
    all[i*2] = s1[i]
    if i < len(s2) {
        all[i*2+1] = s2[i]
    }
}
fmt.Printf("%q\n", all)

输出(在Go Playground上试用):

["house-width" "3" "y" "(5" "house length)"]
[" + " " - " " ^ " " * "]
["house-width" " + " "3" " - " "y" " ^ " "(5" " * " "house length)"]

注意:

如果要修剪运算符的空格,可以使用strings.TrimSpace()函数:

for i, v := range s2 {
    all[i*2+1] = strings.TrimSpace(v)
}
fmt.Printf("%q\n", all)

输出:

["house-width" "+" "3" "-" "y" "^" "(5" "*" "house length)"]

答案 1 :(得分:1)

如果您之后计划解析表达式,则必须进行一些更改:

  • 包括括号为lexemes
  • 您不能同时将空格破折号作为有效的标识符字符,例如- y3之间的^将是有效的标识符。

完成后,你可以使用一个简单的linear iteration来勒索你的字符串:

package main

import (
    "bytes"
    "fmt"
)

func main() {

    input := `house width + 3 - y ^ (5 * house length)`
    buffr := bytes.NewBuffer(nil)
    outpt := make([]string, 0)

    for _, r := range input {
        if r == '+' || r == '-' || r == '*' || r == '/' || r == '^' || r == '(' || r == ')' || (r >= '0' && r <= '9') {
            bs := bytes.TrimSpace(buffr.Bytes())
            if len(bs) > 0 {
                outpt = append(outpt, (string)(bs))
            }
            outpt = append(outpt, (string)(r))
            buffr.Reset()
        } else {
            buffr.WriteRune(r)
        }
    }

    fmt.Printf("%#v\n", outpt)

}

一旦学会了,请使用Dijkstra的shunting-yard algorithm来构建AST或直接评估表达式。

答案 2 :(得分:0)

我认为FindAll()可能就是这样。

扩展正则表达式:

 \s*                           # Trim preceding whitespace
 (                             # (1 start), Operator/Non-Operator chars
      (?:                           # Cluster group
           \w -                          # word dash
        |  - \w                          # or, dash word
        |  [^+\-/*^]                     # or, a non-operator char
      )+                            # End cluster, do 1 to many times
   |                              # or,
      [+\-/*^]                      # A single simple math operator
 )                             # (1 end)
 \s*                           # Trim trailing whitespace

Go code snippet:

http://play.golang.org/p/bHZ21B6Tzi

package main

import (
"log"
"regexp"
)
func main() {
    in := []byte("house-width + 3 - y ^ (5 * house length)")
    rr := regexp.MustCompile("\\s*((?:\\w-|-\\w|[^+\\-/*^])+|[+\\-/*^])\\s*")
    s := r.FindAll( in, -1 )
    for _, ss:=range s{
      log.Println(string(ss))
    }
}

输出:

 house-width 
 + 
 3 
 - 
 y 
 ^ 
 (5 
 * 
 house length)