Golang比较两个YAML文件并更新它们

发布于 2025-01-23 05:00:33 字数 2022 浏览 0 评论 0原文

我是戈兰的新手。我正在尝试比较两个YAML文件,并更新第二个文件的值,如果该特定键的第1个YAML中有任何新值。

因此,文件是格式的:这些是​​示例yaml文件。真正的YAML文件具有每个密钥的不同数据类型的嵌套复杂地图。 第1 YAML:

name: john
city: washington

第二个YAML:

name: peter
city: washington

第二个YAML文件的最终结果应为:

name: john
city: washington

尝试使用Unmarshal为两个YAML文件创建MAP String接口。但是如何比较两个地图。试图在地图的每个键上循环,并在第二个yaml地图中搜索该键。如果键存在在第二个YAML地图中更新该值。但是我无法实施。有什么建议/更好的想法吗?

编辑:更新的代码

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "github.com/imdario/mergo"
    "gopkg.in/yaml.v3"
)

func main() {

    yfile, err := ioutil.ReadFile("C:/Users/212764682/lifecycle/userconfig.yaml")

    if err != nil {

        log.Fatal(err)
    }

    data := make(map[string]interface{})

    err2 := yaml.Unmarshal(yfile, &data)

    if err2 != nil {

        log.Fatal(err2)
    } else {
        
        yfile1, err3 := ioutil.ReadFile("C:/Users/212764682/lifecycle/conf.yaml")
        yfile2, err4 := ioutil.ReadFile("C:/Users/212764682/lifecycle/prof.yaml")

        if err3 != nil && err4 != nil {

            log.Fatal(err3)
            log.Fatal(err4)
        } else {
            dat := make(map[string]interface{})
            dat2 := make(map[string]interface{})
            err5 := yaml.Unmarshal(yfile1, &dat)
            err6 := yaml.Unmarshal(yfile2, &dat2)

            _ = err5
            _ = err6

            for key1, element1 := range data {
                for key2, element2 := range dat {
                    if key1 == key2 {
                        if element1 == element2 {

                        } else {
                            element2 = element1
                        }
                    } else {
                        dat[key1] = data[key1]
                    }
                }

            }
        }

    }

}

,因此我想将数据的每个密钥与DAT进行比较。如果该密钥存在于DAT中,请检查数据中的值。如果dat的值不同,请使用该密钥中的数据值进行更新。另外,如果DAT中存在数据的任何键,请在DAT中附加该密钥。但无法正确实施。

Im a newbie in golang. I am trying to compare two yaml files and update the 2nd file's value if there is any new value in 1st yaml for that particular key.

So the files are of format: These are sample yaml files. Real yaml files have much more nested complicated maps with different datatypes for each key.
1st yaml:

name: john
city: washington

2nd yaml:

name: peter
city: washington

Final result for 2nd yaml file should be:

name: john
city: washington

Tried creating a map string interface for both yaml files using unmarshal. But having trouble how to compare both maps. Was trying to loop over each key of map and search for that key in 2nd yaml map. If key exists update the value in 2nd yaml map. But i am not able to implement that. Any suggestions/better ideas?

Edit: Updated code

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "github.com/imdario/mergo"
    "gopkg.in/yaml.v3"
)

func main() {

    yfile, err := ioutil.ReadFile("C:/Users/212764682/lifecycle/userconfig.yaml")

    if err != nil {

        log.Fatal(err)
    }

    data := make(map[string]interface{})

    err2 := yaml.Unmarshal(yfile, &data)

    if err2 != nil {

        log.Fatal(err2)
    } else {
        
        yfile1, err3 := ioutil.ReadFile("C:/Users/212764682/lifecycle/conf.yaml")
        yfile2, err4 := ioutil.ReadFile("C:/Users/212764682/lifecycle/prof.yaml")

        if err3 != nil && err4 != nil {

            log.Fatal(err3)
            log.Fatal(err4)
        } else {
            dat := make(map[string]interface{})
            dat2 := make(map[string]interface{})
            err5 := yaml.Unmarshal(yfile1, &dat)
            err6 := yaml.Unmarshal(yfile2, &dat2)

            _ = err5
            _ = err6

            for key1, element1 := range data {
                for key2, element2 := range dat {
                    if key1 == key2 {
                        if element1 == element2 {

                        } else {
                            element2 = element1
                        }
                    } else {
                        dat[key1] = data[key1]
                    }
                }

            }
        }

    }

}

So im want to compare each key of data with dat. If that key exists in dat, check for value in data. If value different in dat, update with value of data in dat for that key. Also, if any key of data dosent exist in dat, then append that key in dat. But not able to implement it correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柳絮泡泡 2025-01-30 05:00:33

您可以尝试比较地图,然后如果键存在,然后将其更新。这是使用您的案例的一些示例。

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "gopkg.in/yaml.v3"
)

func main() {
    // read file
    yfile1, err := ioutil.ReadFile("file1.yaml")
    if err != nil {
        log.Fatal(err)
        return
    }

    yfile2, err := ioutil.ReadFile("file2.yaml")
    if err != nil {
        log.Fatal(err)
        return
    }

    // unmarshal ymal
    data1 := make(map[string]interface{})
    if err := yaml.Unmarshal(yfile1, &data1); err != nil {
        log.Fatal(err)
        return
    }

    data2 := make(map[string]interface{})
    if err := yaml.Unmarshal(yfile2, &data2); err != nil {
        log.Fatal(err)
        return
    }

    // from this we can iterate the key in data2 then check whether it exists in data1
    // if so then we can update the value in data2

    // iterate key in data2
    for key2 := range data2 {
        // check whether key2 exists in data1
        if val1, ok := data1[key2]; ok {
            // update the value of key2 in data2
            data2[key2] = val1
        }
    }

    fmt.Printf("data2: %v", data2)
    // output:
    // data2: map[city:washington name:john]

    // you can write the data2 into ymal
    newYfile2, err := yaml.Marshal(&data2)
    if err != nil {
        log.Fatal(err)
        return
    }

    // write to file
    if err = ioutil.WriteFile("new_file2.yaml", newYfile2, 0644); err != nil {
        log.Fatal(err)
        return
    }
}

内部new_file2.yaml将是这样的:

city: washington
name: john

您需要选择的一件事是GO中的地图无法维护订单(Afaik Go没有内置orderedmap键入每2022年5月7日),因此新文件中的顺序键将是随机的

附加注意事项:对于错误处理,您最好立即处理(立即在遇到错误之后)。这是一篇关于它的好文章错误处理并进行

You can try to compare the map and then update it if the key exists. Here's some example using your case.

package main

import (
    "fmt"
    "io/ioutil"
    "log"

    "gopkg.in/yaml.v3"
)

func main() {
    // read file
    yfile1, err := ioutil.ReadFile("file1.yaml")
    if err != nil {
        log.Fatal(err)
        return
    }

    yfile2, err := ioutil.ReadFile("file2.yaml")
    if err != nil {
        log.Fatal(err)
        return
    }

    // unmarshal ymal
    data1 := make(map[string]interface{})
    if err := yaml.Unmarshal(yfile1, &data1); err != nil {
        log.Fatal(err)
        return
    }

    data2 := make(map[string]interface{})
    if err := yaml.Unmarshal(yfile2, &data2); err != nil {
        log.Fatal(err)
        return
    }

    // from this we can iterate the key in data2 then check whether it exists in data1
    // if so then we can update the value in data2

    // iterate key in data2
    for key2 := range data2 {
        // check whether key2 exists in data1
        if val1, ok := data1[key2]; ok {
            // update the value of key2 in data2
            data2[key2] = val1
        }
    }

    fmt.Printf("data2: %v", data2)
    // output:
    // data2: map[city:washington name:john]

    // you can write the data2 into ymal
    newYfile2, err := yaml.Marshal(&data2)
    if err != nil {
        log.Fatal(err)
        return
    }

    // write to file
    if err = ioutil.WriteFile("new_file2.yaml", newYfile2, 0644); err != nil {
        log.Fatal(err)
        return
    }
}

Inside new_file2.yaml will be like this:

city: washington
name: john

One thing that you need to take a not is that map in Go doesn't maintain the order (AFAIK Go doesn't have built-in OrderedMap type per 7 May 2022) so the order key in the new file will be random

Additional note: for error handling, you better handle it right away (right after you got the error). Here's a good article about it Error handling and Go

老娘不死你永远是小三 2025-01-30 05:00:33

我相信有一个地图包,因为1.18。如果您不在乎添加到目标映射中的新密钥,则可以使用其复制函数。

  func副本[m〜map [k] v,k bodable,v any](dst,src m)
 

复制在SRC中复制所有键/值对,将它们添加到DST中。当DST中已经存在SRC中的密钥时,DST中的值将被与SRC中的密钥关联的值所覆盖。

source code> source code 该功能非常简单:

func Copy[M ~map[K]V, K comparable, V any](dst, src M) {
    for k, v := range src {
        dst[k] = v
    }
}

您也可以自己做。以下代码来自。与上面的复制功能不同,它递归起作用:

func mergeMaps(a, b map[string]interface{}) map[string]interface{} {
    out := make(map[string]interface{}, len(a))
    for k, v := range a {
        out[k] = v
    }
    for k, v := range b {
        if v, ok := v.(map[string]interface{}); ok {
            if bv, ok := out[k]; ok {
                if bv, ok := bv.(map[string]interface{}); ok {
                    out[k] = mergeMaps(bv, v)
                    continue
                }
            }
        }
        out[k] = v
    }
    return out
}

There is a maps package, since 1.18 I believe. If you don't care about new keys being added to the destination map you can use its copy function.

func Copy[M ~map[K]V, K comparable, V any](dst, src M)

Copy copies all key/value pairs in src adding them to dst. When a key in src is already present in dst, the value in dst will be overwritten by the value associated with the key in src.

The source code of that function is very simple:

func Copy[M ~map[K]V, K comparable, V any](dst, src M) {
    for k, v := range src {
        dst[k] = v
    }
}

You could also do it yourself. The below code is from the helm source code. Unlike the copy function above, it works recursivly:

func mergeMaps(a, b map[string]interface{}) map[string]interface{} {
    out := make(map[string]interface{}, len(a))
    for k, v := range a {
        out[k] = v
    }
    for k, v := range b {
        if v, ok := v.(map[string]interface{}); ok {
            if bv, ok := out[k]; ok {
                if bv, ok := bv.(map[string]interface{}); ok {
                    out[k] = mergeMaps(bv, v)
                    continue
                }
            }
        }
        out[k] = v
    }
    return out
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文