How to check if the user has entered a single letter? - bash

I am reading a character and want to check if that is single character and is a letter. My code is below:
#!/usr/bin/bash
read -p "Enter something: " char
if [[ ${#char} != 1 && "$char" != *[a-z]* ]]; then
echo "Not a valid input"
else
echo "Its a valid input"
fi
The o/p is below:
[root#host-7 ~]# sh -x t
+ read -p 'Enter something: ' char
Enter something: 1
+ [[ 1 != 1 ]]
+ echo 'Its a valid input'
Its a valid input
While executing the script only first condition is getting executed and its not checking the second condition.

It is not evaluating 2nd condition because first condition is failing as you're entering only 1 character in input and there is && between 2 conditions.
If you enter 2 character input like ab then you'll see both conditions getting evaluated.
You can use -n1 to restrict input to one character only like this:
#!/usr/bin/bash
read -n1 -p "Enter something: " char
echo
if [[ "$char" != *[a-z]* ]];then
echo "Not a valid input"
else
echo "Its a valid input"
fi
And run it as:
bash -x ./t

If you wish to test for a single letter, you can use the POSIX character class [[:alpha:]] or equivalently [a-zA-Z]. No need to check the length or use wildcards as a single bash pattern will only test multiple occurrences of a match when using extglob optional patterns.
read -p "Enter something: " char
if [[ $char != [[:alpha:]] ]]; then
echo "Not a valid input"
else
echo "It's a valid input"
fi

You can simply change the if statement to:
if [[ $char != [a-zA-Z] ]]; then
It will check if $char is a single character and is a letter (a-z,A-Z).
Example:
#!/bin/bash
read -p "Enter something: " char
if [[ $char != [a-zA-Z] ]]; then
echo "Not a valid input"
else
echo "Its a valid input"
fi
Output will be like this:
ab : inavlid
a : valid
1 : invalid
12 : invalid
A : valid
AB : invalid

Related

Not able to validate string in shell script

echo "enter variable"
read var
if[[ ${var} = ^[a-zA-Z][a-zA-Z0-9]{0,25}$ ]];then
echo "valid"
else
echo "invalid"
fi
I'm trying to validate(starting with a character followed by alphanumeric, no special character). 26 characters allowed.
For every input, it gives valid. What am I missing here?
This should work (please note the tilde):
echo "enter variable"
read var
if [[ ${var} =~ ^[a-zA-Z][a-zA-Z0-9]{0,25}$ ]] ; then
echo "valid"
else
echo "invalid"
fi

How to check the conditon whether a number has letters and digits that are greater than 10 using shell script

how to check both conditions in shell script, that whether a number has alphabets and that number should not consist of more than 10 digits
re='[a-zA-Z]'
read -p "Enter time:" epoch_time
if [[ "$epoch_time" =~ $re ]] -a [[ "${#time}" -gt 10 ]];then
echo "not a valid time"
else
echo "entered time is valid"
fi
You can write your regular expression to validate just for numbers and to check for input length.
re='^[0-9]+{0,10}$'; read -p "Enter time:" epoch_time
if [[ $epoch_time =~ $re ]]; then echo "entered time is valid"; else "not valid time" fi

Looping input command

How can we have input from user in DD/MM/YYYY format in shell code such that till user does not provides input in this format the same prompt is printed again and again.
printf "Please Enter START Date(DD/MM/YYYY)\n"
read date1
how to check in this that if date is provided in DD/MM/YYYY format or not. and if not then how to start this loop again?
This solution firstly checks the syntax of all the tokens
of the input and then using the command date checks if the
the input is a valid date. For instance 30/02/2014 has
a correct syntax but it is not a valid date. Please note
that the date command accepts the format MM/DD/YYYY.
#!/bin/bash
while [ 1 ]; do
IFS="/" read -p "Please Enter START Date(DD/MM/YYYY): " d m y
if [[ $d != [0-9][0-9] ]]; then echo "Day format invalid"; continue; fi
if [[ $m != [0-9][0-9] ]]; then echo "Month format invalid"; continue; fi
if [[ $y != [0-9][0-9][0-9][0-9] ]]; then echo "Year format invalid"; continue; fi
if date -d "$m/$d/$y" > /dev/null; then
date1="$d/$m/$y"
break
fi
done
# Here you can use $date1 as you prefer. For instance:
echo $date1
Try this one:
until read -p "Please Enter START Date (DD/MM/YYYY): " && [[ $REPLY == [0-9][0-9]/[0-9][0-9]/[0-9][0-9] ]]; do
## echo "Please enter in proper (DD/MM/YYYY) format."
continue
done
The echo part is just optional that you could consider adding.
By default, read places input in $REPLY variable if no variable is specified, but you could have a custom one if you like.
read -p "Please Enter START Date (DD/MM/YYYY): " INPUT && [[ $INPUT == ...
For a bit more sh-compatible and based on your own format you can have this:
#!/bin/sh
while :; do
printf "Please Enter START Date(DD/MM/YYYY)\n"
read date1
case "$date1" in
[0-9][0-9]/[0-9][0-9]/[0-9][0-9])
break
;;
esac
done

Check input consists only of numeric characters in shell script

I need to check that the input consists only of numeric characters. I have the code below, but it didn't work properly.
if [[ $1 =~ [0-9] ]]; then
echo "Invalid input"
fi
It should give true only for 678686 not for yy66666.
How about this:-
re='^[0-9]+$'
if ! [[ $Number =~ $re ]] ; then
echo "error: Invalid input" >&2; exit 1
fi
or
case $Number in
''|*[!0-9]*) echo nonnumeric;;
*) echo numeric;;
esac
Try using start/end anchors with your pattern. If you don't, the match succeeds with a part of a test string. Don't forget that you have to use a pattern matching the complete test string if you follow this suggestion.
if [[ $1 =~ ^[0-9]+$ ]]; then
echo "Invalid input"
fi
Check out this SO post for more details.

How do I prompt a user for confirmation in bash script? [duplicate]

This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
Closed 9 years ago.
I want to put a quick "are you sure?" prompt for confirmation at the top of a potentially dangerous bash script, what's the easiest/best way to do this?
read -p "Are you sure? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
# do dangerous stuff
fi
I incorporated levislevis85's suggestion (thanks!) and added the -n option to read to accept one character without the need to press Enter. You can use one or both of these.
Also, the negated form might look like this:
read -p "Are you sure? " -n 1 -r
echo # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
[[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell
fi
However, as pointed out by Erich, under some circumstances such as a syntax error caused by the script being run in the wrong shell, the negated form could allow the script to continue to the "dangerous stuff". The failure mode should favor the safest outcome so only the first, non-negated if should be used.
Explanation:
The read command outputs the prompt (-p "prompt") then accepts one character (-n 1) and accepts backslashes literally (-r) (otherwise read would see the backslash as an escape and wait for a second character). The default variable for read to store the result in is $REPLY if you don't supply a name like this: read -p "my prompt" -n 1 -r my_var
The if statement uses a regular expression to check if the character in $REPLY matches (=~) an upper or lower case "Y". The regular expression used here says "a string starting (^) and consisting solely of one of a list of characters in a bracket expression ([Yy]) and ending ($)". The anchors (^ and $) prevent matching longer strings. In this case they help reinforce the one-character limit set in the read command.
The negated form uses the logical "not" operator (!) to match (=~) any character that is not "Y" or "y". An alternative way to express this is less readable and doesn't as clearly express the intent in my opinion in this instance. However, this is what it would look like: if [[ $REPLY =~ ^[^Yy]$ ]]
use case/esac.
read -p "Continue (y/n)?" choice
case "$choice" in
y|Y ) echo "yes";;
n|N ) echo "no";;
* ) echo "invalid";;
esac
advantage:
neater
can use "OR" condition easier
can use character range, eg [yY][eE][sS] to accept word "yes", where any of its characters may be in lowercase or in uppercase.
Try the read shell builtin:
read -p "Continue (y/n)?" CONT
if [ "$CONT" = "y" ]; then
echo "yaaa";
else
echo "booo";
fi
This way you get 'y' 'yes' or 'Enter'
read -r -p "Are you sure? [Y/n]" response
response=${response,,} # tolower
if [[ $response =~ ^(y| ) ]] || [[ -z $response ]]; then
your-action-here
fi
If you are using zsh try this:
read "response?Are you sure ? [Y/n] "
response=${response:l} #tolower
if [[ $response =~ ^(y| ) ]] || [[ -z $response ]]; then
your-action-here
fi
Here's the function I use :
function ask_yes_or_no() {
read -p "$1 ([y]es or [N]o): "
case $(echo $REPLY | tr '[A-Z]' '[a-z]') in
y|yes) echo "yes" ;;
*) echo "no" ;;
esac
}
And an example using it:
if [[ "no" == $(ask_yes_or_no "Are you sure?") || \
"no" == $(ask_yes_or_no "Are you *really* sure?") ]]
then
echo "Skipped."
exit 0
fi
# Do something really dangerous...
The output is always "yes" or "no"
It's "no" by default
Everything except "y" or "yes" returns "no", so it's pretty safe for a dangerous bash script
And it's case insensitive, "Y", "Yes", or "YES" work as "yes".
I hope you like it,
Cheers!
This what I found elsewhere, is there a better possible version?
read -p "Are you sure you wish to continue?"
if [ "$REPLY" != "yes" ]; then
exit
fi
[[ -f ./${sname} ]] && read -p "File exists. Are you sure? " -n 1
[[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
used this in a function to look for an existing file and prompt before overwriting.
echo are you sure?
read x
if [ "$x" = "yes" ]
then
# do the dangerous stuff
fi
#!/bin/bash
echo Please, enter your name
read NAME
echo "Hi $NAME!"
if [ "x$NAME" = "xyes" ] ; then
# do something
fi
I s a short script to read in bash and echo back results.
qnd: use
read VARNAME
echo $VARNAME
for a one line response without readline support. Then test $VARNAME however you want.

Resources