在没有任何外部依赖的情况下在bash中修改yaml文件

Pra*_*shi 2 text-processing yaml

我在 YAML 文件中有多个配置,我需要使用 Bash 脚本更改一些参数。是否可以?我想避免使用任何外部依赖。

我的 YAML 看起来像

%YAML 1.2
---
name: mic
components:
- name: Mic
  parameters:
    period_count: 4
    alsa_device_name: "pulse"

---
name: speaker
components:
- name: Speaker
  parameters:
    period_duration_ms: 20
    period_count: 4
    alsa_device_name: "pulse"
Run Code Online (Sandbox Code Playgroud)

我希望它表现得像如果我提供--mic logitec --speaker hk34那么就应该修改alsa_device_name两个micspeaker我的config来

%YAML 1.2
---
name: mic
components:
- name: Mic
  parameters:
    period_count: 4
    alsa_device_name: "logitec"

---
name: speaker
components:
- name: Speaker
  parameters:
    period_duration_ms: 20
    period_count: 4
    alsa_device_name: "hk34"
Run Code Online (Sandbox Code Playgroud)

是否可以仅使用 Bash 来实现,如果可以,如何实现?现在我正在使用 Python 脚本,但这增加了对 have 的额外依赖python3,这是我想避免的。

Ini*_*ian 5

首先,使用面向行的工具解析像 YAML 这样具有明确定义的语法的语言是一个坏主意。不要在生产中使用它!绝不。

有一些语法感知工具可以通过命令行解析 YAML,比如PythonyqGoyq。它们支持 YAML 中的结构,如锚点、块文字,标准面向行的工具无法理解这些结构。

对于像上面这样的一次处理,您可以使用awk

BEGIN {
    map["name: mic"] = "\"logitec\""
    map["name: speaker"] = "\"hk34\""
}

match($0, "name: mic") || match($0, "name: speaker") {
    key = substr($0, RSTART, RLENGTH)
}

/alsa_device_name/ {
    sub(/:.*/, ": " map[key])
}

{ print }
Run Code Online (Sandbox Code Playgroud)

您可以将上述内容放在awk脚本 ( .awk) 中并将其作为awk -f script.awk yaml命令行运行或作为命令行的一部分运行。您还可以将命令行中的值定义为

awk -v mic='"logitec"' -v speaker='"hk34"' -f script.awk yaml
Run Code Online (Sandbox Code Playgroud)

并将BEGIN块中的参数处理为

BEGIN {
    map["name: mic"] = mic
    map["name: speaker"] = speaker
}
Run Code Online (Sandbox Code Playgroud)

另请注意,您的输入不是有效的 YAML 文件,标题行%YAML 1.2会使大多数标准 YAML 解析器在您的输入语法上引发错误。