SilentUK
SilentUK

Reputation: 195

Parsing text in BASH

I have a username system. The user picks a username, password and pin number and this is saved into UPP.db. I want to be able to parse this text so that a user can either be edited (Change password) or Deleted (Remove Line). I have coded a solution for both but both return me with an error and jump to the "Else" part of my If statement. I will provide the code for the edit section as the delete is pretty similar and would be redundant providing both.

echo "Please enter the username you wish to edit"
read usernamecheck

usernamesearch=$( grep $usernamecheck\$ UPP.db | cut -d" " -f1 )

if [ $usernamecheck = $usernamesearch ]
        then
        echo "Please enter $usernamesearch PIN"
                read pincheck
                pinupdate=$( grep $pincheck\$ UPP.db | cut -d" " -f3 )
                if [[ $pin = $pinupdate && $usernamecheck = $usernamesearch ]]
                then
                    echo "The user `grep "$pin"\$ UPP.db | cut -d" " -f1`'s password is about to be changed "
                    echo "Please enter the new password"
                    read newpass
                    passwordcheck=$( grep $pincheck\$ UPP.db | cut -d" " -f2 )
                    sed -i "s/$passwordcheck/$newpass/g" UPP.db
                    echo "Password changed"
                else
                    echo "The PIN is incorrect"
                fi
        else
                echo "This username is not reconised"
fi
;;

Upvotes: 1

Views: 52

Answers (1)

glenn jackman
glenn jackman

Reputation: 246764

string equality comparisons will be more precise than regular expressions. Here, I use awk not grep to enable that. You might want to keep the bash man page handy while you read this.

read -p "Please enter the username you wish to edit: " usernamecheck

# extract all the fields at once
read -r db_user db_pass db_pin < <(
    awk -v name="$usernamecheck" '$1 == name {print; exit}' UPP.db
)

if [[ -z $db_user ]]; then
    echo "This username is not reconised"
else
    read -p "Please enter $db_user PIN: " pincheck
    if [[ "$db_pin" != "$pincheck" ]]; then
        echo "The PIN is incorrect"
    else
        echo "Changing password for user $db_user:"
        while true; do 
            read -s -p "Please enter the new password: " newpass
            echo
            read -s -p "Please re-enter the new password: " newpass2
            echo
            if [[ "$newpass" == "$newpass2" ]]; then
                break
            fi
            echo "Passwords do not match. Try again."
        done

        ln UPP.db "UPP.db.$(date "+%Y%m%d%H%M%S")"    # create a backup copy
        temp=$(mktemp)

        # update the password
        awk -v newpw="$newpass" -v name="$db_user" '
            $1 == name {$2 = newpw}
            {print}
        ' UPP.db > "$temp" && mv "$temp" UPP.db

        echo "Password changed"
    fi
fi

Style tip: in an if-else-end construct, put the smaller block first, then the else-block is close to the condition. Aids readability.

If this plain text file, containing user passwords, is anywhere close to the internet, you're f*cked.

Upvotes: 2

Related Questions