解析文本文件以匹配字符串和提取值(在Golang中)

解析文本文件以匹配字符串和提取值(在Golang中),go,Go,我正在绞尽脑汁寻找一种可能很普遍的需求,但我在网上找不到任何例子 我有这样一个文件: answer VNET_1_DHCP yes answer VNET_1_DHCP_CFG_HASH 4CF2C196E368CE83B9D1895C5E05301CDFDEBCA0 answer VNET_1_HOSTONLY_NETMASK 255.255.255.0 answer VNET_1_HOSTONLY_SUBNET 192.168.224.0 answer VNET_1_

我正在绞尽脑汁寻找一种可能很普遍的需求,但我在网上找不到任何例子

我有这样一个文件:

  answer VNET_1_DHCP yes
  answer VNET_1_DHCP_CFG_HASH 4CF2C196E368CE83B9D1895C5E05301CDFDEBCA0  
  answer VNET_1_HOSTONLY_NETMASK 255.255.255.0
  answer VNET_1_HOSTONLY_SUBNET 192.168.224.0
  answer VNET_1_VIRTUAL_ADAPTER yes
  answer VNET_8_DHCP yes
  answer VNET_8_DHCP_CFG_HASH D326C0BC7FF6C38C57AF341F9075E576C175B250
  answer VNET_8_HOSTONLY_NETMASK 255.255.255.0
  answer VNET_8_HOSTONLY_SUBNET 172.16.102.0
  answer VNET_8_NAT yes
  answer VNET_8_VIRTUAL_ADAPTER yes
我需要提取特定子网的VNET编号(192.168.224.0)。VNET数量可能会有所不同(理论上,子网甚至可能不存在)。因此,我需要匹配子网是否存在,如果存在,则提取网络号(
1

我发现在BASH中实现这一点非常容易:

 if grep -q 192.168.224.0 ./networking; then
      echo "The ${VMNET_SUBNET} network already exists"
      NETWORK_NUMBER=$(grep ${VMNET_SUBNET} ./networking | cut -d'_' -f 2)
      echo NETWORK_NUMBER  
 else <do something to create it.....> 
if grep-q 192.168.224.0./networking;然后
echo“已存在${VMNET_SUBNET}网络”
网络号=$(grep${VMNET_SUBNET}./网络切-d'-f 2)
回音网络号
其他的
我正试图找到最简单的方法来实现这个使用围棋

谢谢

您可以使用:


游乐场:。

这里有一种基于@ainar-g答案的强大的数据解析方法:

这里的目标是使用以下类型将每个VNET的属性存储在映射中:

type vnet map[int]map[string]string
此代码:

var re = regexp.MustCompile(`.*VNET_(\d+)_([^\s]+) (.*)`)
func ReadVnet(r io.Reader) vnet {
    s := bufio.NewScanner(r)
    v := make(vnet)

    for s.Scan() {
        matches := re.FindStringSubmatch(s.Text())
        id, err := strconv.Atoi(matches[1])
        if err != nil {
            continue
        }

        if _, ok := v[id]; !ok {
            v[id] = make(map[string]string)
        }
        v[id][matches[2]] = matches[3]
    }

    return v
}
创建有问题的地图:

map[1:map[DHCP:yes DHCP_CFG_HASH:4CF2C196E368CE83B9D1895C5E05301CDFDEBCA0 HOSTONLY_NETMASK:255.255.255.0 HOSTONLY_SUBNET:192.168.224.0 VIRTUAL_ADAPTER:yes] 8:map[DHCP:yes DHCP_CFG_HASH:D326C0BC7FF6C38C57AF341F9075E576C175B250 HOSTONLY_NETMASK:255.255.255.0 HOSTONLY_SUBNET:172.16.102.0 NAT:yes VIRTUAL_ADAPTER:yes]]
现在,您可以在地图上迭代以查找感兴趣的项目:

func main() {
    v := ReadVnet(bytes.NewBufferString(text))

    for id, properties := range v {
        if ip, ok := properties["HOSTONLY_SUBNET"]; ok && ip == "192.168.224.0" {
            fmt.Println(id)
            return
        }
    }
}

这是一个没有regexp的版本:

  idxEnd := strings.Index(txt, "192.168.224.0")
  idxVNET := strings.LastIndex(txt[:idxEnd], "VNET_")
  beginNumber := idxVNET + 5
  length := strings.Index(txt[beginNumber:idxEnd], "_")
  number, _ := strconv.Atoi(txt[beginNumber : beginNumber+length])
  fmt.Printf("number: %T %v\n", number, number)

您是否可以尝试在一个非常(非常)大的字符串上执行此操作,它应该会更快。

显然:上面的代码段中的VMNET_SUBNET=“192.168.224.0”!谢谢我喜欢简短的解决方案(尽管另一个也很好)。我在找一些短的,而且剪得很好。Regexp是如此强大(但对我来说是如此敌对)。谢谢
  idxEnd := strings.Index(txt, "192.168.224.0")
  idxVNET := strings.LastIndex(txt[:idxEnd], "VNET_")
  beginNumber := idxVNET + 5
  length := strings.Index(txt[beginNumber:idxEnd], "_")
  number, _ := strconv.Atoi(txt[beginNumber : beginNumber+length])
  fmt.Printf("number: %T %v\n", number, number)