Home > OS >  Palindrome checker using user input and while loop in bash
Palindrome checker using user input and while loop in bash

Time:12-30

I'm trying to make a bash script that checks if a word is a palindrome for my homework assignment, but I can't get my while loop to work properly. The script should keep running and asking for a palindrome, until the user gives a palindrome. Can someone more experienced help me out with this and maybe explain what I did wrong.

#!/bin/bash

if [ $# -le 2 ]           
then 
    echo "Enter the word"
    read input                  
fi 
echo $input > temp         
reverse=`rev temp`     
echo $reverse              


while [ ! $input==$reverse ]
do  echo "Not a palindrome"
    read input 

done
echo "it is a palindrome"    
rm temp

CodePudding user response:

Something like this should do:

#!/bin/bash
set -euo pipefail;

while true; do
    echo -n "Enter the word: ";
    IFS=$'\n\t ' read -d$'\n' -r inputword restofsentence;
    if [[ -n "${inputword}" && -z "${restofsentence}" ]] ; then
        reverse="$( rev <( echo "${inputword}" ) )";
        if [[ "${reverse}" == "${inputword}" ]] ; then
            echo "it is a palindrome";
            exit 0;
        else
            echo "Not a palindrome";
            echo "";
            echo "";
        fi;
    fi;
done;

I'm not sure what function the $# (number of cli arguments) served, in your example, as you weren't using the cli arguments; so i've left that part out.


As for what it all does:

set -euo pipefail;

Effectively enables "strict mode". Making BASH less of a shitty scripting language. It doesn't really have much of an effect in this script, but it's good practice to always have that in every script by default.

while true; do

Start a loop and keep repeating it forever.

echo -n "Enter the word: ";

The -n inhibits the usual newline at the end of the sentence.

IFS=$'\n\t '

Explicitly sets the Internal Field Separator. This means bash's interpretation of what a word is, is the input "broken apart" on newlines (\n), tab characters (\t) and spaces (' '); generally this is the default value, but its always good practise to manually set IFS either on a per-script basis, or for every read-like command.

read -d$'\n' -r inputword restofsentence;

Reads user input up to delimiter newline (-d$'\n'), meaning the enter key. Don't allow backslash-escapes -r to be used for things like multi-line input. The inputline is split into words based on the earlier IFS; after which the first word goes into inputword, and potential 2nd/3rd/...-words go into restofsentence.

if [[ -n "${inputword}" && -z "${restofsentence}" ]] ; then

We expect inputword to have a value (non-empty) and we expect restofsentence to be empty. If that is not the case, we simply let the while-loop repeat and ask for input again. This way we never deal with empty input (because inputword would be empty) nor with multi-word input (because restofsentence wouldn't be empty).

reverse="$( rev <( echo "${inputword}" ) )";

We echo the inputword into a virtual file, and pass that to the rev program, which echos the reverse value. We store that in variable reverse.

The fact that we aren't using a real file (which is stored on the filesystem, instead of only in memory), saves us from having to clean that up later.

if [[ "${reverse}" == "${inputword}" ]] ; then

We compare if the inputword and reverse are identical, if they are then we're dealing with a palindrome.

exit 0;

Once we've had a successful palindrome, we quit (exitcode 0 indicates there was no error).


The program (specifically the while-loop) keeps repeating forever until a successful palindrome is found.

CodePudding user response:

Try this one:

#!/bin/bash

while :; do
    read -p "Enter a word: "

    if [[ ${REPLY} == "$(rev <(printf %s "${REPLY}"))" ]]; then
        echo "It is a palindrome."
        break
    fi

    echo "Not a palindrome."
done

Alternatively it can be done simpler like this but this isn't right since theoretically "It is a palindrome." will be still sent even if the loop breaking is not caused by correct input but other errors.

#!/bin/bash

while read -p "Enter a word: "; [[ ${REPLY} != "$(rev <(printf %s "${REPLY}"))" ]]; do
    echo "Not a palindrome."
done

echo "It is a palindrome"

By the way it uses Process Substitution.

One can create a function that reverses strings instead and that should be trivial but it's optional scope.

CodePudding user response:

First get it working.
You want to check for one argument. When the argument is given, assign it to input. Quote $input avoiding problems witch special characters and spaces. Add spaces around == to make it compare and calculate reverse again in the loop. I also used $(rev temp) what works better than backtics.

#!/bin/bash
if [ $# -ne 1 ]
then
    echo "Enter the word"
    read input
else
  input="$1"
fi
echo "$input" > temp
reverse=$(rev temp)
echo "$reverse"

while [ ! "$input" == "$reverse" ]
do
  echo "Not a palindrome"
  read input
  echo "$input" > temp
  reverse=$(rev temp)
done
echo "it is a palindrome"
rm temp

You can avoid a tmp file like this:

#!/bin/bash
if [ $# -ne 1 ]
then
    echo "Enter the word"
    read input
else
  input="$1"
fi
while [ ! "$input" == "$(rev <<< "${input}")" ]
do
  echo "Not a palindrome"
  read input
done
echo "it is a palindrome"
  • Related