bashhugotoml

Bash script to insert/update nested values in Hugo hugo.toml — not working as expected


I'm trying to write a Bash script that updates the hugo.toml config file of a Hugo static site to insert a slogan parameter in the [languages.xx.params] section of each language.

Goal:

For each language listed in the [languages] table of hugo.toml, I want to:

Example:

Given this config:

[languages.es]
languageName = "Español"
contentDir = "content/es"

[languages.fr]
languageName = "Français"
contentDir = "content/fr"
[languages.fr.params]
description = "A test site"

After running the script, I want to see:

[languages.fr.params]
description = "A test site"
slogan = "Bonjour"

[languages.es.params]
slogan = "Hola"

What I tried

I wrote this Bash script (full code at bottom), which:

The logic tries to:

But when I run it:

Question

What’s the best way to reliably insert or update a single key inside a TOML file via Bash?

Is there a clean way to handle [languages.xx.params] blocks properly?


If needed, I can also share the full script I'm using.

https://github.com/wilonweb/multi-author/blob/main/batch/set-slogan.sh



Solution

  • You should use a specialized parser to parse TOML which is a structured standard such as JSON or YAML, for example dasel. The script could look like the following script.bash:

    #!/usr/bin/env bash
    
    for lang in $(dasel -r toml -f LANGUAGES.toml 'languages.all().key()' --write plain)
    do
        printf "Type slogan for %s: " "$lang"
        read -r slogan
        dasel put -r toml -w toml -f LANGUAGES.toml -v "$slogan" languages."$lang".params.slogan
    done
    

    For example - we have the following LANGUAGES.toml like the one you posted in your question:

    [languages.es]
    languageName = "Español"
    contentDir = "content/es"
    
    [languages.fr]
    languageName = "Français"
    contentDir = "content/fr"
    [languages.fr.params]
    description = "A test site"
    

    Run the script:

    $ ./script.bash
    Type slogan for es: Hola
    Type slogan for fr: Bonjour
    

    The file will have the following contents:

    [languages]
      [languages.es]
        contentDir = 'content/es'
        languageName = 'Español'
    
        [languages.es.params]
          slogan = 'Hola'
    
      [languages.fr]
        contentDir = 'content/fr'
        languageName = 'Français'
    
        [languages.fr.params]
          description = 'A test site'
          slogan = 'Bonjour'