2015-12-23 58 views
2

我抓住了我的腦袋,似乎這種需求可能很普遍,但我無法在Web上找到任何示例。解析文本文件以匹配字符串並提取值(在Golang中)

我有一個這樣的文件:

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 

我需要提取特定子網(192.168.224.0)的VNET數。 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.....> 

我試圖找到實現這個使用的最便捷方式。

謝謝。

+0

顯然:VMNET_SUBNET =「192.168.224.0」在 – mreferre

回答

3

您可以使用regular expression

re := regexp.MustCompile(`.*VNET_(\d+)_.*192.168.224.0`) 
matches := re.FindStringSubmatch(text) 
fmt.Println(matches[1]) 

遊樂場:http://play.golang.org/p/NQlA2BObtU

+0

之上的代碼段Doh!謝謝!我喜歡這個簡短的解決方案(儘管其他人也能正常工作)。我正在尋找一些簡短的東西,並且很好地削減了它。正則表達式非常強大(但對我來說如此敵對)。謝謝! – mreferre

4

下面是分析這些數據基礎上@ ainar-G的回答一條有效的途徑:

http://play.golang.org/p/6-PELcLvVz

這裏的目標是爲每個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 
     } 
    } 
} 
1

這是一個沒有正則表達式的一個版本:

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) 

會你試圖在一個非常大的字符串上這樣做,它應該會更快。

相關問題