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
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 echo
s 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.