Haswell
Haswell

Reputation: 1642

shell: Replacing a part of Line in a file

I am new to shell programming and had to do the following task. I have a file with following line at line number 28 (static).

page.sysauth = "Admin"

I wanted to replace this line using a shell script each time a new entry to sysauth be made.

page.sysauth = {"Admin", "root"} page.sysauth = {"Admin", "root", "newAdmin"} etc.

Also I would want to remove entries from this sysauth variable

page.sysauth = {"Admin", "root", "newAdmin"}
page.sysauth = {"Admin", "root"}
page.sysauth = "Admin"

Please provide pointers in achieving this.

EDIT: Thank you for the inputs: Assumption: First entry should be present. eg: page.sysauth="Admin" Script fails when page.sysauth=______ (empty).

Here's my working script sysauth_adt.sh

#!/bin/bash
add () {
    sed -i~ -e '28 { s/= "\(.*\)"/= {"\1"}/; # Add curlies to a single entry.
                     s/}/,"'"$entry"'"}/     # Add the new entry.
                   }' "$file"
}

remove () {
    sed -i~ -e '28 { s/"'"$entry"'"//;      # Remove the entry.
                     s/,}/}/;               # Remove the trailing comma (entry was last).
                     s/{,/{/;               # Remove the leading comma (entry was first).
                     s/,,/,/;               # Remove surplus comma (entry was inside).
                     s/{"\([^,]*\)"}/"\1"/  # Remove curlies for single entry.
                   }' "$file"
}

if (( $# == 3 )) ; then
    file=$1
    action=$2
    entry=$3
    if [[ $action == add ]] ; then
        if head -n28 $1 | tail -n1 | grep -q $3 ; then
                echo 0 
        else
                add
        fi
    elif [[ $action == remove ]] ; then
        if head -n28 $1 | tail -n1 | grep -q $3 ; then
                remove
        else
                echo 0
        fi
    fi
else
    echo "Usage: ${0#*/} file (add | remove) entry" >&2
    exit 1
fi

Upvotes: 1

Views: 60

Answers (2)

NeronLeVelu
NeronLeVelu

Reputation: 10039

awk -F '[[:blank:]]+=[[:blank:]]+' '
   # load every single entry
   NR != 28 && FNR == NR && $1 ~ /^page.sysauth$/ && $0 !~ /\{.*\}/ { aSysAdd[ ++SysAdd] = $2}
   # load special line 28
   NR == 28 {
      gsub( /^{|}$/, "", Datas = $2)
      SysOrg = split( Datas, aSysOrg, /[[:blank:]]*,[[:blank:]]*/)
      }
   # print standard lines
   FNR != NR && $1 !~ /^page.sysauth$/ { print }
   # print line 28 (new version)
   FNR != NR && FNR == 28 {
      printf "page.sysauth = {" aSysOrg[ 1]
      for( i = 2; i <= SysOrg; i++) printf ", %s", aSysOrg[ i]
      for( i = 1; i <= SysAdd; i++) printf ", %s", aSysAdd[ i]
      print "}"
   # don't print other page.sysauth
   }
 ' YourFile YourFile > YourFile.new
mv YourFile.new YourFile

Using awk with 2 read (the double YourFile is not an error and mandatory)

Upvotes: 1

choroba
choroba

Reputation: 241858

If your entries will always be single words with no commas, you can use simple sed scripts:

#!/bin/bash
add () {
    sed -i~ -e '28 { s/= "\(.*\)"/= {"\1"}/; # Add curlies to a single entry.
                     s/}/,"'"$entry"'"}/     # Add the new entry.
                   }' "$file"
}

remove () {
    sed -i~ -e '28 { s/"'"$entry"'"//;      # Remove the entry.
                     s/,}/}/;               # Remove the trailing comma (entry was last).
                     s/{,/{/;               # Remove the leading comma (entry was first).
                     s/,,/,/;               # Remove surplus comma (entry was inside).
                     s/{"\([^,]*\)"}/"\1"/  # Remove curlies for single entry.
                   }' "$file"
}

if (( $# == 3 )) ; then
    file=$1
    action=$2
    entry=$3
    if [[ $action == add ]] ; then
        add
    elif [[ $action == remove ]] ; then
        remove
    fi
else
    echo "Usage: ${0#*/} file (add | remove) entry" >&2
    exit 1
fi

The script doesn't check whether an entry already exists in the list when adding or removing it. For more complicated tasks, I'd probably switch to a real programming language.

Upvotes: 1

Related Questions