【问题标题】:Extracting variable in YAML from a shell script从 shell 脚本中提取 YAML 中的变量
【发布时间】:2021-10-23 18:55:57
【问题描述】:

我有一个由以下内容组成的 YAML 文件:

acceleration_matrix:
  # 1ere row: x
  - [20, 0, 0, 15, 15]
  # 2eme row: y
  - [0, 15, 0, 0, 0]
  # 3eme row: z
  - [0, 0, 30, 15, -15]
  # 4eme row: repere de l'acceleration
  - [0, 0, 0, 0, 0]
  # 5eme row: loadcase_id
  - [1, 2, 3, 4, 5]

我想提取最后一行的最后一个值(在本例中为5),不使用 shell 脚本。 使用this article,我编码:

#!/bin/bash

function parse_yaml {
   local prefix=$2
   local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
   sed -ne "s|^\($s\):|\1|" \
        -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
        -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p"  $1 |
   awk -F$fs '{
      indent = length($1)/2;
      vname[indent] = $2;
      for (i in vname) {if (i > indent) {delete vname[i]}}
      if (length($3) > 0) {
         vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
         printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
      }
   }'
}

parse_yaml nastran_acceleration_matrix.yml

echo $acceleration_matrix

但由于我是 shell 新手,我找不到如何提取值。 我想要的只是:

set number_load_case = ### acceleration_matrix[-1,-1] ### (I'm more used to coding in python thus the -1 aka last row/column)

有人可以帮帮我吗?

提前致谢!

【问题讨论】:

  • 哪个具体程序名为yq你正在使用?一个是 jq 的包装器,使用标准的 jq 语法;另一个是自己独立开发的东西,有自己的语言。

标签: linux bash shell awk yq


【解决方案1】:

我建议使用适当的解析器,例如yq。然后你的任务(acceleration_matrix 的最后一个元素的最后一个值)变得像

yq eval '.acceleration_matrix[-1][-1]' nastran_acceleration_matrix.yml

【讨论】:

  • 感谢您的帮助。但是,我不能使用 yq,因为我从另一个无法添加库的软件中调用脚本...
  • 我设法安装并远程调用它,以便您的命令有效!非常感谢!
【解决方案2】:

一个awk 的想法完全基于 OP 的样本输入:

$ awk -F'[] ]' '{lastid=$(NF-1)} END {print lastid}' test.yaml
5

地点:

  • -F'[] ]' - 将输入字段分隔符设置为 &lt;space&gt;]
  • lastid=$(NF-1) - 跟踪最后一个字段
  • END {print lastid} - 打印我们保存的最后一个'next to last field'
  • 最终结果:扫描整个文件,在我们进行过程中保存在最后一个字段旁边,并在文件末尾打印/输出我们捕获的最后一个“倒数第二个”字段

存储在bash 变量中:

$ number_load_case=$(awk -F'[] ]' '{lastid=$(NF-1)} END {print lastid}' test.yaml)
$ echo "${number_load_case}"
5

注意事项:

  • 如果输入的格式没有像 OPs 示例中那样完全正确,这显然会产生不正确的结果(例如,如果最后一行为空白,则 awk 将失败并出现错误:fatal: attempt to access field -1
  • 如前所述,yq 之类的内容更适合此问题,尤其是在格式化不像 OP 示例中那样“漂亮”时
  • 对于不太“漂亮”的格式,以及无法使用类似yq 的内容,可以编写更强大的解析器(例如,在awk 中)

【讨论】:

  • 非常感谢您的帮助!实际上,由于这将为用户修改 yaml 实现,所以我有点害怕这样做不仅仅是更改正确的值并弄乱整个工作流程(将在其中实现代码),但是谢谢非常喜欢!
【解决方案3】:

安装 syaml

 $ pip install shyaml      ## installation

conda env create -f environment.yml -n cat test.yaml | shyaml get-value conda_env_name

你可以在安装完 shyaml 之后尝试上面的命令。

如果这对您不起作用,那么您可以在 bash 脚本中尝试 'jq''yq' ,这会将您的 yaml 解析为 json,然后您可以从 JSON 读取值,之后您可以从 bash 本身运行命令。

【讨论】:

  • 谢谢。当前设置不允许我在创建 conda 之前安装任何 pip 包。那么使用sed/grep/awk 可以实现这一点吗?
  • 我只知道 sed 命令用于文件操作,但从未使用过。我确信 bash 脚本。使用 bash,您可以轻松实现这一目标。在那里你不需要安装任何包。
猜你喜欢
  • 2020-09-05
  • 2013-06-15
  • 1970-01-01
  • 2019-01-06
  • 2016-07-09
  • 1970-01-01
  • 2021-12-01
  • 2014-03-29
相关资源
最近更新 更多