英文:
Parsing of text file to match string and extract value (in 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 <执行创建操作.....>
我正在尝试找到使用Go实现这个的最简单方法。
谢谢。
英文:
I am scratching my head around a need that seems to be potentially common but I couldn't locate any example on the web.
I have a file like this:
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
I need to extract the VNET number of a specific subnet (192.168.224.0). VNET numbers could vary (and the subnet could, in theory, not even exist). So I need to match if the subnet exists, and if exists extract the network number (1
in this example).
I found it to be SUPER easy to implement this in 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.....>
I am trying to find the easiest way to implement this using Go.
Thanks.
答案1
得分: 10
你可以使用正则表达式(regular expression)来实现:
re := regexp.MustCompile(`.*VNET_(\d+)_.*192.168.224.0`)
matches := re.FindStringSubmatch(text)
fmt.Println(matches[1])
Playground: http://play.golang.org/p/NQlA2BObtU.
英文:
You can use a regular expression:
re := regexp.MustCompile(`.*VNET_(\d+)_.*192.168.224.0`)
matches := re.FindStringSubmatch(text)
fmt.Println(matches[1])
Playground: http://play.golang.org/p/NQlA2BObtU.
答案2
得分: 5
这是一种基于 @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
}
}
}
英文:
Here is a robust way to parse these data that builds on @ainar-g's answer:
http://play.golang.org/p/6-PELcLvVz
The goal here is to store the properties for each VNET in a map, using the following type:
type vnet map[int]map[string]string
This code:
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
}
creates the map in question:
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]]
Now you can iterate on the map to find the item of interest:
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
}
}
}
答案3
得分: 3
这是一个没有正则表达式的版本:
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)
如果你尝试在一个非常(非常)大的字符串上执行这个操作,它应该会更快。
英文:
This is a version without 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)
Would you try to do that on a very (very) big string, it should be faster.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论