0

This might be so simple but I need to do this:

I have a file name a.sh, and it contains few lines as below

# firstname banuka
firstcolor green
lastname jananath
# age 25

And I want to write firstname banuka to this file, so it would look like

echo "firstname banuka" > a.sh

BUT, before writing firstname banuka I want to check if file already has that value (or line)

As you can see in the file content of a.sh, the part we are going to write (firstname banuka) can be already there but with a comment.

So if it has a comment,
   1. I want to un-comment it (remove `#` in front of `firstname banuka`)
If no comment and no line which says `firstname banuka`,
   2. Add the line `firstname banuka`
If no comment and line is already there,
   3. skip (don't write `firstname banuka` part to file)

Can someone please help me?

user13456401
  • 439
  • 1
  • 6
  • 12

3 Answers3

2
string="firstname banuka"
file=./a.sh

grep -qwi "^[^[:alnum:]]*$string$" "$file" && \
sed -i "s,\(^[^[:alnum:]]*\)\($string$\),\2,i" "$file" || \
printf "\n%b\n" "$string" >> "$file"
alecxs
  • 701
  • 8
  • 17
1

You need to use a programming language that can scan for patterns, has variables, and has conditional contructs. awk is one such language:

awk -v text="firstname banuka" '
    $0 ~ text {
        found = 1          # remember that we have seen it
        sub(/^ *# */, "")  # remove the comment, if there is one
    }
    {print}
    END {if (!found) {print text}}
' file

This will not edit the file, just print it out. With GNU awk, if you want to edit the file in-place:

gawk -i inplace -v text="..." '...' file

With plain bash you would write

found=false
while IFS= read -r line; do
    if [[ "$line" == *"firstname banuka"* ]]; then
        found=true
        if [[ "$line" =~ ^[[:blank:]]*[#][[:blank:]]*(.+) ]]; then
            line="${BASH_REMATCH[1]}"
        fi
    fi
    echo "$line"
done < file
$found || echo "firstname banuka"
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Sorry, this doesn't write to the file. and I added `$found || echo "firstname banuka" >> test.txt`, but it doesn't un-comment the text if it has already in the file commented. – user13456401 Jul 19 '20 at 15:42
1

Alternative Bash implementation

#!/usr/bin/env bash

found=false
while IFS= read -r line; do
    if [[ "$line" =~ ^([[:blank:]]*[#][[:blank:]]*)?(firstname banuka) ]]; then
        echo "${BASH_REMATCH[2]}"
        found=true
    else
      echo "$line"
    fi
done < a.txt
$found || echo "firstname banuka"
Léa Gris
  • 17,497
  • 4
  • 32
  • 41
  • This doesn't work when there is a commented `firstname banuka`, if it is commented I want to uncomment it – user13456401 Jul 19 '20 at 15:39
  • @user13456401 insert a `typeset -p BASH_REMATCH` before `echo "${BASH_REMATCH[2]}"`; and check the output. I suspect you are not using Bash but zsh instead. This is for Bash only. – Léa Gris Jul 19 '20 at 15:48