【问题标题】:Linux shell get value of a field from a yml fileLinux shell 从 yml 文件中获取字段的值
【发布时间】:2015-07-10 06:16:36
【问题描述】:

我有一个类似的 database.yml 文件

development:
  adapter: mysql2
  encoding: utf8
  database: d360
  host: localhost
  username: root
  password: password

test:
  adapter: mysql2
  encoding: utf8
  database: sample
  host: localhost
  username: root
  password: password

现在,我想要测试环境数据库的值(即所示 YAML 的 sample)。 我们如何使用 sed 做到这一点?

【问题讨论】:

    标签: yaml


    【解决方案1】:

    这相当简单,不用sed,而是使用适当的shell 工具。首先,如果您需要将 sample 保留在变量中以供以后使用,那么使用 bash substring replacement 来隔离 Test:/database 上的 sample 将起作用,如下所示: 行:

    $ db=$(grep -A3 'test:' database.yml | tail -n1); db=${db//*database: /}; echo "$db"
    sample
    

    或者对于可以转储到命令行的更短的解决方案,删除变量和命令替换并使用cut之类的工具:

    $ grep -A3 'test:' database.yml | tail -n1 | cut -c 13-
    sample
    

    或者,awk,简单地说:

    $ grep -A3 'test:' database.yml | tail -n1 | awk '{ print $2}'
    sample
    

    命令替换(即var=$(stuff))中可以使用所有不同的方式来将sample 存储在var 中,这只是您更愿意使用哪种方式的问题。我想你明白了。

    【讨论】:

    • 非常感谢大卫。这就是我一直在寻找的:)
    • 我在db=${db//*database: /} 之前见过这个,但是我们怎么称呼它?
    • @bretonics - 这是一个带有子字符串替换的参数扩展。它采用=${db 中的现有变量db,然后将*database: 每个 出现// 替换为/...(无)。 (注意关闭 '/' 是隐含的)。因此,您只需从 db 中删除每次出现的 *database: ,并将修改后的结果分配回 db
    • 这种类型的代码假设你知道输入文件的格式......如果是这样,为什么不grep -m2 database | tail -1 | awk '{print $2}'
    【解决方案2】:

    有比sed 更好的工具。您可能会被困在一个最小的系统上,但寻找答案的其他人可能不会。

    yq 的 python 版本的行为类似于 jq

    $ pip3 install yq
    $ yq -r .test.database database.yml
    sample
    

    shyaml 也可以,但有一个奇怪的限制,你只能重定向到它:

    $ pip3 install shyaml
    $ shyaml get-value test.database < database.yml
    sample
    

    如果perl 在附近并且您安装了 YAML:

    $ cpan YAML
    $ perl -MYAML -le 'print YAML::LoadFile(shift)->{test}{database}' database.yml
    sample
    

    或者,如果你想要ruby

    $ ruby -r yaml -e 'puts YAML.load_file(ARGV[0])["test"]["database"]' database.yml
    sample
    

    【讨论】:

      【解决方案3】:

      在 Ubuntu 上,安装 yq:

      $ sudo apt update
      $ sudo apt install snapd
      $ sudo snap install yq
      

      使用yq:

      $ value=$(yq r database.yml test.database)`
      

      【讨论】:

      • snap 和 Python 包在使用上是有区别的。 snap 版本(4.6.0):yq .test.database database.yml -jpython 版本(2.12.0):yq eval .test.database database.yml
      【解决方案4】:

      显然,shell 本身不支持 YAML。但 sed 也不是 YAML 解析器。 grep、tail、cut 等都不是。我很确定您需要一种实际的 语言 来编写适当的解析器。 awk、perl、python、erlang等

      如果您知道您的 YAML 数据将始终以某种方式格式化或以特定顺序保存某些值,那么您可以使用 sed 或 shell 或类似的东西,但是要制作一个可以正常工作的解析器,并且在您指向的任何 ol' YAML 文件上,您都需要模拟其他语言中已经存在的解析器。

      如果您不想编写自己的代码(可能在考虑一些代码后向 StackOverflow 社区寻求帮助),那么一种选择可能是安装像 shyaml 这样的工具,它可以准确地解析文件并给出你权威的内容。一个快速的解决方案很容易实现到你的脚本中,尽管它有一些依赖项(python)。

      【讨论】:

      • 这是一个更好的答案,将带来更好的解决方案(因为当 yaml 文件更改时它们会更少中断......并且相信我 yaml 文件会更改)。
      【解决方案5】:

      对于使用 Homebrew 的 macOS / Linux 用户,yq 可用,并提供类似jq 的体验:

      $ brew install yq
      $ yq eval .test.database database.yml
      sample
      

      【讨论】:

        猜你喜欢
        • 2022-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多