The following bash
script reads a string from the user and tests whether the string fulfills the criteria for a hostname that you seem to want to enforce.
The first of the two patterns used in the case
statement tests for the pathological case of two dots with no characters in-between (this is a pattern that we don't act upon). We test for a string containing at least two dots and no dot at either end with the second pattern. The hostname variable fdqn
is set to the string only if this second pattern matches the string. Note that the string foo..bar
matches the second pattern, which is why we preemptively match the double dot substring with the first pattern.
#!/bin/bash
unset -v count fdqn
while true; do
read -p 'Enter hostname: ' -r
case $REPLY in (*..*) ;; ([!.]*.*.*[!.]) fdqn=$REPLY; break; esac
echo 'Invalid format' >&2
count=$(( count + 1 ))
[ "$count" -eq 2 ] && break
done
if [ -z "$fdqn" ]; then
echo 'No valid hostname entered' >&2
exit 1
fi
printf 'The hostname is "%s"\n' "$fdqn"
The count
variable keeps track of how many times the user has tried to enter a string. We break out of the loop if this variable's value reaches two.
There is no real need to use a case
statement here unless you want to make it a portable sh
script (in which case you would have to do the read
statement differently). With the globbing operator ==
in bash
, the case
statement would be written like below.
if [[ $REPLY == *..* ]]; then
:
elif [[ $REPLY == [!.]*.*.*[!.] ]]; then
fdqn=$REPLY
break
fi
The two tests could also be joined using &&
if the first is negated.
if [[ $REPLY != *..* ]] && [[ $REPLY == [!.]*.*.*[!.] ]]; then
fdqn=$REPLY
break
fi
If you want to avoid getting hostnames containing three dots, then make sure that $REPLY
does not match *.*.*.*
, just like it shouldn't match *..*
.