Home > Mobile >  Updating a config file based on the presence of a specific string
Updating a config file based on the presence of a specific string

Time:10-29

I want to be able to comment and uncomment lines which are "managed" using a bash script.

I am trying to write a script which will update all of the config lines which have the word #managed after them and remove the preceeding # if it exists.

The rest of the config file needs to be left unchanged. The config file looks like this:

configFile.txt

#config1=abc #managed
#config2=abc #managed
config3=abc #managed
config3=abc

This is the script I have created so far. It iterates the file, finds lines which contain "#managed" and detects if they are currently commented.

I need to then write this back to the file, how do I do that?

manage.sh

#!/bin/bash

while read line; do

STR='#managed'
if grep -q "$STR" <<< "$line"; then
  echo "debug - this is managed"

  firstLetter=${$line:0:1}
  if [ "$firstLetter" = "#" ]; then
    echo "Remove the initial # from this line"
  fi
fi

echo "$line"

done < configFile.txt

CodePudding user response:

With your approach using grep and sed.

str='#managed$'
file=ConfigFile.txt

grep -q "^#.*$str" "$file" && sed "/^#.*$str/s/^#//" "$file"

Looping through files ending in *.txt

#!/usr/bin/env bash

str='#managed$'

for file in *.txt; do
  grep -q "^#.*$str" "$file" &&
  sed "/^#.*$str/s/^#//" "$file"
done

  • In place editing with sed requires the -i flag/option but that varies from different version of sed, the GNU version does not require an -i.bak args, while the BSD version does.

On a Mac, ed should be installed by default, so just replace the sed part with.

printf '%s\n' "g/^#.*$str/s/^#//" ,p Q | ed -s "$file"
  • Replace the Q with w to actually write back the changes to the file.

  • Remove the ,p if no output to stdout is needed/required.


On a side note, embedding grep and sed in a shell loop that reads line-by-line the contents of a text file is considered a bad practice from shell users/developers/coders. Say the file has 100k lines, then grep and sed would have to run 100k times too!

CodePudding user response:

This sed one-liner should do the trick:

sed -i.orig '/#managed/s/^#//' configFile.txt

It deletes the # character at the beginning of the line if the line contains the string #managed.


I wouldn't do it in bash (because that would be slower than sed or awk, for instance), but if you want to stick with bash:

#! /bin/bash

while IFS= read -r line; do
    if [[ $line = *'#managed'* && ${line:0:1} = '#' ]]; then
        line=${line:1}
    fi
    printf '%s\n' "$line"
done < configFile.txt > configFile.tmp
mv configFile.txt configFile.txt.orig && mv configFile.tmp configFile.txt
  • Related