Home > Back-end >  Bash Add or replace string in file that meets a few scenarios
Bash Add or replace string in file that meets a few scenarios

Time:12-09

A more complex replace into a file?

I run into this type of issue all of the time and haven't found a great way to deal with it.

I want to place gcache.size=3G into a file and it needs to replace or add depending on the situation:

Situation 1: Append to this line

wsrep_provider_options="cert.optimistic_pa=no"
wsrep_provider_options="cert.optimistic_pa=no;gcache.size=3G;"

Situation 2: append but don't put in double ;;

wsrep_provider_options="cert.optimistic_pa=no;"
wsrep_provider_options="cert.optimistic_pa=no;gcache.size=3G;"

Situation 3: If commented out, just add a new line with the value we want set

#wsrep_provider_options="cert.optimistic_pa=no"
wsrep_provider_options="gcache.size=3G"

Situation 4: If doesn't exist, add it

<line doesn't exist>
wsrep_provider_options="gcache.size=3G"

Situation 5: if it's a different value, replace

wsrep_provider_options="cert.optimistic_pa=no;gcache.size=5G;"
wsrep_provider_options="cert.optimistic_pa=no;gcache.size=3G;"

Is there a clever way to do this?

CodePudding user response:

Either you use some dedicated tool for this like Ansible (lineinfile) or you have to code it yourself.

#! /bin/bash

override ()
{
  local var_is_set=false
  local opt_is_set
  local -a options
  local option
  
  while read -r line; do
    echo "line: $line" >&2
    if [[ $line =~ ^(.?)wsrep_provider_options=\"(.*)\" ]]; then
      var_is_set=true
      if [[ "${BASH_REMATCH[1]}" == '#' ]]; then
        printf '%s\n' "$line" 'wsrep_provider_options="gcache.size=3G"'
      else
        printf 'wsrep_provider_options="'
        IFS=';' read -ra options <<< "${BASH_REMATCH[2]}"
        opt_is_set=false
        for option in "${options[@]}"; do
          if [[ $option =~ ^gcache\.size= ]]; then
            opt_is_set=true
            printf 'gcache.size=3G;'
          else
            printf 'option ##%s##\n' "$option" >&2
            if [[ $option ]]; then
              printf '%s;' "$option"
            fi
          fi
        done
        if [[ $opt_is_set == false ]]; then
          printf "gcache.size=3G;"
        fi
        printf '"\n'
      fi
    else
      printf '%s\n' "$line"
    fi
  done
  if [[ $var_is_set == false ]]; then
    printf '%s\n' 'wsrep_provider_options="gcache.size=3G"'
  fi
}

testcase=()
testdata=()

testcase =('Situation 1: Append to this line')
testdata =('wsrep_provider_options="cert.optimistic_pa=no"')

testcase =('Situation 2: append but don'\''t put in double ;;')
testdata =('wsrep_provider_options="cert.optimistic_pa=no;"')

testcase =('Situation 3: If commented out, just add a new line with the value we want set')
testdata =('#wsrep_provider_options="cert.optimistic_pa=no"')

testcase =('Situation 4: If doesn'\''t exist, add it')
testdata =('')

testcase =('Situation 5: if it'\''s a different value, replace')
testdata =('wsrep_provider_options="cert.optimistic_pa=no;gcache.size=5G;"')

for ((i=0 ; i < "${#testcase[@]}" ; i  )); do
  printf "$(tput bold)%s$(tput sgr0)\n" "${testcase[$i]}"
  printf 'Input:\n%s\n' "${testdata[$i]}"
  printf 'Output:\n%s\n' "$(override <<< "${testdata[$i]}")"
  printf '\n'
done

Notice: SO's syntax highlighting does not work in many cases. They do not feel responsible for the glitches, because the highlighting is done by a third party tool and they are satisfied with the results.

  •  Tags:  
  • bash
  • Related