go parse the string

Scenes

Sometimes, the message is not received from our program json or xml message body of such common formats, is an ordinary string, such as below this message:

A调用失败率过高
------
业务方:X项目
时间点:2020-01-10 16:25:00.360047+08:00
------

For the program, it is such a string:

"A调用失败率过高\n------\n业务方:X项目\n时间点:2020-01-10 16:25:00.360047+08:00\n------\n"

This string can not be used json or xml package provides functions to parse, we can only handwritten parsing code.

Our demand is that parse out the type of alarm, the business side, and the point in time to save a map inside, so that subsequent processing will be more convenient.

Parsing a string of common functions

Strings using functions provided by the package can be accomplished basic string parsing.

Parsing a string commonly has the following functions:

1. Split string partition function

For example, in our example that message, between the message header and message content through "------ \ n" to separate the substring, then when we resolve this message, the first step should be the title and content of the message are parsed.

Function for segmenting the bag strings strings is Split, used as follows:

message := strings.Split(src, sep)
//src:需要被分割的字符串
//sep:用于分割字符串的子串
//message:返回的是一个string类型的数组,存储分割之后的多个子串

Examples of messages to be used in the test:

message := strings.Split(msg, "\n------\n")
fmt.Println(len(message))
for msgId, subMsg := range message {
	fmt.Println(msgId, subMsg)
}

The results are as follows:

Can be seen, there are two strings divided substrings "\ n ------ \ n", it is divided to three sub-string of the first substring message header, the message content of the second substring , the last sub-string is an empty string.

2. determines whether a string contains the specified Contains substring

Sometimes, we do not need a string to parse out each character, we need only contain a particular substring by string, you can know the information in the message we need.

strings package, the function determines whether there is a substring the Contains, used as follows:

res := strings.Contains(src, substr)
//src:源字符串
//substr:想判断是否存在的子串
//res:判断结果,bool类型,存在为true,不存在为false

Or use examples in the test message, for example, we want the message headers (the step has been acquired by the split) in obtaining the type of call, write:

if strings.Contains(message[0], "A调用") {
	callType = "callA"
} else if strings.Contains(message[0], "B调用") {
	callType = "callB"
} else if strings.Contains(message[0], "C调用") {
	callType = "callC"
} else {
	return "", nil, errors.New("Unknown call.")
}

So we get to a call type, and store them in a callType variable.

3. Find substring position Index

In the example, if we want to get the "business side" information, you first need to find the substring "business side:" The location of this substring, and then get the content behind it.

Function is used to find strings package position is a substring Index, used as follows:

loc := strings.Index(src, substr)
//src:源字符串
//substr:需要查找的字符串
//loc:被查找字符串第一次出现的位置,如果未找到,返回-1

Get string "business party" follows from the example test procedure:

messageLen := len(message)
if loc := strings.Index(message, "业务方"); loc < messageLen {
	if endLoc := strings.Index(message[loc:], "\n"); endLoc > 10 {
		value := message[loc+10 : loc+endLoc]
		return value
	}
	return ""
}

 Program, after finding position "business side" appears, you need to start from this position to find the first "\ n", because in front of the "\ n" is the business side of information, here need to be reminded, strings. Index (message [loc:], "\ n") the result of this sentence, is relative to the loc substring starting position, not the position of the entire message , it is easy to forget the first time to write, so pay attention.

Complete program

Finally parsing strings in the complete program example:

package main

import (
	"errors"
	"fmt"
	"strings"
)

const alertMsg  = "A调用失败率过高\n------\n业务方:X项目\n时间点:2020-01-10 16:25:00.360047+08:00\n------\n"

func getValueByKey(message, key string) string {
	messageLen := len(message)
	if loc := strings.Index(message, key); loc < messageLen {
		if endLoc := strings.Index(message[loc:], "\n"); endLoc > 10 {
			value := message[loc+10 : loc+endLoc]
			return value
		}
		return ""
	}
	return ""
}

func parseMsg(msg string) (string, []map[string]string, error) {
	//根据分割线分割字符串,第一个子串是标题,后面的子串为报警消息内容
	message := strings.Split(msg, "------\n")
	if len(message) < 3 {
		return "", nil, errors.New("Parse alert message failed.")
	}

	//根据报警标题确定调用类型
	var callType string
	if strings.Contains(message[0], "A调用") {
		callType = "callA"
	} else if strings.Contains(message[0], "B调用") {
		callType = "callB"
	} else if strings.Contains(message[0], "C调用") {
		callType = "callC"
	} else {
		return "", nil, errors.New("Unknown call.")
	}

	//根据报警消息内容解析业务方,时间
	var alertInfo []map[string]string
	for i := 1; i < len(message) - 1; i++ {
		tempInfo := make(map[string]string)
		tempInfo["project"] = getValueByKey(message[i], "业务方")
		tempInfo["time"] = getValueByKey(message[i], "时间点")
		if tempInfo["project"] == "" || tempInfo["time"] == "" {
			return "", nil, errors.New("Parse alert info failed.")
		}
		alertInfo = append(alertInfo, tempInfo)
	}
	return callType, alertInfo, nil
}

func main()  {
	//fmt.Println(alertMsg)
	callType, alertInfo, err := parseMsg(alertMsg)
	if err != nil {
		fmt.Println(err.Error())
	} else {
		fmt.Println(callType, alertInfo)
	}
}

Attention to detail in the above procedure, each function executed, must take into account unusual circumstances. Program results are as follows:

 

Published 39 original articles · won praise 25 · views 120 000 +

Guess you like

Origin blog.csdn.net/u013536232/article/details/104196177