Marcos Peres
Marcos Peres

Reputation: 31

Replacing lines in a yaml file

I'm trying to create a script that will replace the parameters of a given network interface in the 01-network-manager-all.yaml file.

The file looks something like this:

# Let NetworkManager manage all devices on this system
network:
  version: 2
  renderer: NetworkManager
  ethernets:
    enp0s3:
      dhcp4: no
      dhcp6: no
      addresses: [195.10.10.10/24]
      gateway4: 195.10.10.10
      nameservers:
        addresses: [1.1.1.1]
    enp0s8:
      dhcp4: no
      dhcp6: no
      addresses: [196.10.10.10/24]
      gateway4: 196.10.10.10
      nameservers:
        addresses: [1.1.1.1]
    enp0s9:
      dhcp4: no
      dhcp6: no
      addresses: [197.10.10.10/24]
      gateway4: 197.10.10.10
      nameservers:
        addresses: [1.1.1.1]

Say I want to replace the lines concerning enp0s8 and leave the others as they are.

The output would look something like this:

# Let NetworkManager manage all devices on this system
network:
  version: 2
  renderer: NetworkManager
  ethernets:
    enp0s3:
      dhcp4: no
      dhcp6: no
      addresses: [195.10.10.10/24]
      gateway4: 195.10.10.10
      nameservers:
        addresses: [1.1.1.1]
    enp0s8:
      dhcp4: no
      dhcp6: no
      addresses: [196.250.250.125/24]
      gateway4: 196.250.250.125
      nameservers:
        addresses: [8.8.8.8]
    enp0s9:
      dhcp4: no
      dhcp6: no
      addresses: [197.10.10.10/24]
      gateway4: 197.10.10.10
      nameservers:
        addresses: [1.1.1.1]

In this case, I'm looking for a sed - or any other command - that will replace everything in between enp0s8 and enp0s9.

I'm not a very experienced Bash user, any tip will be appreciated.

My poor attempt at doing so

sed -e '/^ *enp0s8:/,/^ *^enp0s9:/s/$CONFIG_TO_ADD/' "/etc/netplan/01-network-manager-all.yaml"

Upvotes: 3

Views: 397

Answers (4)

Philippe
Philippe

Reputation: 26727

Using yq :

yq eval '.network.ethernets.enp0s8 |= (.addresses = ["196.250.250.125/24"] |
                                       .gateway4  = "196.250.250.125" |
                                       .nameservers.addresses = ["8.8.8.8"]
                                      )' file.yml

Upvotes: 3

Jetchisel
Jetchisel

Reputation: 7831

Just in case someone is interested.

Using ed if available/acceptable.

#!/bin/sh

ethernets=enp0s8
gateway=196.250.250.125
address=196.250.250.125/24
name_server_address=8.8.8.8

ed -s file.yaml <<-EOF
  g/$ethernets/;/nameservers/s/^\\([[:blank:]]*gateway4:[^ ]*\\).*/\\1 $gateway/\\
  -1s|^\\([[:blank:]]*addresses: \[\\).*\\(\]\\)$|\\1$address\\2|
  g/$ethernets/;/nameservers:/;/addresses:/s|^\\([[:blank:]]*addresses: \\[\\).*\\(\\]\\)$|\\1$name_server_address\\2|
  ,p
  Q
EOF

  • Change the last digit of enp0s if the changes should be made at the other section/block, which is pointing to enp0s8 right now.

  • Not a yaml parser/editor and not robust as the other solutions but It can do the job.

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204426

$ cat new
      dhcp4: no
      dhcp6: no
      addresses: [196.250.250.125/24]
      gateway4: 196.250.250.125
      nameservers:
        addresses: [8.8.8.8]

$ awk '
    NR==FNR { new=new ORS $0; next }
    /^    [^ ]/ { if ( f=($1=="enp0s8:") ) print $0 new }
    !f
' new file
# Let NetworkManager manage all devices on this system
network:
  version: 2
  renderer: NetworkManager
  ethernets:
    enp0s3:
      dhcp4: no
      dhcp6: no
      addresses: [195.10.10.10/24]
      gateway4: 195.10.10.10
      nameservers:
        addresses: [1.1.1.1]
    enp0s8:
      dhcp4: no
      dhcp6: no
      addresses: [196.250.250.125/24]
      gateway4: 196.250.250.125
      nameservers:
        addresses: [8.8.8.8]
    enp0s9:
      dhcp4: no
      dhcp6: no
      addresses: [197.10.10.10/24]
      gateway4: 197.10.10.10
      nameservers:
        addresses: [1.1.1.1]

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 247092

I'd use a tool that understands YAML instead of plain text manipulation. For example, ruby:

$ ruby -e '
    require "yaml"
    data = YAML.safe_load_file(ARGV[0])
    net = data["network"]["ethernets"]["enp0s8"]
    net["addresses"] = ["196.250.250.125/24"]
    net["gateway4"] = "196.250.250.125"
    net["nameservers"]["addresses"] = ["8.8.8.8"]
    puts data.to_yaml
' file.yml
---
network:
  version: 2
  renderer: NetworkManager
  ethernets:
    enp0s3:
      dhcp4: false
      dhcp6: false
      addresses:
      - 195.10.10.10/24
      gateway4: 195.10.10.10
      nameservers:
        addresses:
        - 1.1.1.1
    enp0s8:
      dhcp4: false
      dhcp6: false
      addresses:
      - 196.250.250.125/24
      gateway4: 196.250.250.125
      nameservers:
        addresses:
        - 8.8.8.8
    enp0s9:
      dhcp4: false
      dhcp6: false
      addresses:
      - 197.10.10.10/24
      gateway4: 197.10.10.10
      nameservers:
        addresses:
        - 1.1.1.1

Upvotes: 3

Related Questions