how to test for user input

how to test for user input

am 08.01.2008 22:36:41 von littlehelphere

I have a script and part of requires input from the user for time in
the form of h(hours), m(minutes) or d(days)
for example 1d eqautes to 1 day.
I would like to set up a test in ksh to verify the input is in
fact a numeric value followed by one of the letters above. Basically
if a user enter 1f I want the script to ask for input again. If the
user enters 1m then the script should go on. I understand this is a
if then statement but I cannot get what to test for. I have tried the
"||" but no luck. Thanks in advance.

Re: how to test for user input

am 08.01.2008 22:44:45 von Ed Morton

littlehelphere@gmail.com wrote:
> I have a script and part of requires input from the user for time in
> the form of h(hours), m(minutes) or d(days)
> for example 1d eqautes to 1 day.
> I would like to set up a test in ksh to verify the input is in
> fact a numeric value followed by one of the letters above. Basically
> if a user enter 1f I want the script to ask for input again. If the
> user enters 1m then the script should go on. I understand this is a
> if then statement but I cannot get what to test for. I have tried the
> "||" but no luck. Thanks in advance.

Not, it's not an "if" statement, it's a "case" statement:

read time
case $time in
[0-9]*[hmd] ) echo "good" ;;
* ) echo "bad" ;;
esac

Regards,

Ed.

Re: how to test for user input

am 08.01.2008 22:52:58 von littlehelphere

On Jan 8, 4:44 pm, Ed Morton wrote:
> littlehelph...@gmail.com wrote:
> > I have a script and part of requires input from the user for time in
> > the form of h(hours), m(minutes) or d(days)
> > for example 1d eqautes to 1 day.
> > I would like to set up a test in ksh to verify the input is in
> > fact a numeric value followed by one of the letters above. Basically
> > if a user enter 1f I want the script to ask for input again. If the
> > user enters 1m then the script should go on. I understand this is a
> > if then statement but I cannot get what to test for. I have tried the
> > "||" but no luck. Thanks in advance.
>
> Not, it's not an "if" statement, it's a "case" statement:
>
> read time
> case $time in
> [0-9]*[hmd] ) echo "good" ;;
> * ) echo "bad" ;;
> esac
>
> Regards,
>
> Ed.

Thanks - two quick questions
1) How do I set this up so if the test fails the user is forced to
enter a valid response?
2) Could this be an if/then statement or in a case like this is a case
statement the "best practice"?

Re: how to test for user input

am 09.01.2008 00:45:55 von Ed Morton

littlehelphere@gmail.com wrote:
> On Jan 8, 4:44 pm, Ed Morton wrote:
>
>>littlehelph...@gmail.com wrote:
>>
>>> I have a script and part of requires input from the user for time in
>>>the form of h(hours), m(minutes) or d(days)
>>>for example 1d eqautes to 1 day.
>>> I would like to set up a test in ksh to verify the input is in
>>>fact a numeric value followed by one of the letters above. Basically
>>>if a user enter 1f I want the script to ask for input again. If the
>>>user enters 1m then the script should go on. I understand this is a
>>>if then statement but I cannot get what to test for. I have tried the
>>>"||" but no luck. Thanks in advance.
>>
>>Not, it's not an "if" statement, it's a "case" statement:
>>
>>read time
>>case $time in
>> [0-9]*[hmd] ) echo "good" ;;
>> * ) echo "bad" ;;
>>esac
>>
>>Regards,
>>
>> Ed.
>
>
> Thanks - two quick questions
> 1) How do I set this up so if the test fails the user is forced to
> enter a valid response?


time=""
while [ -z "$time" ]
do
printf "Enter a time in \"[0-9]*[hmd]\" format: " >&2
IFS= read -r time
case $time in
[0-9]*[hmd] ) : ;;
* ) printf "Invalid time \"%s\", try again.\n" "$time" >&2
time=""
;;
esac
done

> 2) Could this be an if/then statement or in a case like this is a case
> statement the "best practice"?

I wouldn't even think of trying that with an if/then. "case" is best
practice.

Ed.

Re: how to test for user input

am 09.01.2008 12:31:25 von Stephane CHAZELAS

On Tue, 08 Jan 2008 15:44:45 -0600, Ed Morton wrote:
[...]
> case $time in
> [0-9]*[hmd] ) echo "good" ;;
> * ) echo "bad" ;;
> esac
[...]

This would say that 0Zd is "good". Remember that the globbing
"*" is not the same as the regexp "*".

case $time in
("" | *[!hmd] | ? | *[!0-9]*?) echo >&2 bad;;
(*) echo good;;
esac

or:

if expr "x$time" : 'x[0-9]\{1,\}[hmd]$' > /dev/null; then
echo good
else
echo >&2 bad
fi

--
Stephane

Re: how to test for user input

am 09.01.2008 15:03:32 von Ed Morton

Stephane Chazelas wrote:
> On Tue, 08 Jan 2008 15:44:45 -0600, Ed Morton wrote:
> [...]
>
>>case $time in
>> [0-9]*[hmd] ) echo "good" ;;
>> * ) echo "bad" ;;
>>esac
>
> [...]
>
> This would say that 0Zd is "good". Remember that the globbing
> "*" is not the same as the regexp "*".

Oh, yeah... Thanks.

> case $time in
> ("" | *[!hmd] | ? | *[!0-9]*?) echo >&2 bad;;
> (*) echo good;;
> esac

I'd probably write it as:

case $time in
*[!0-9]*? ) echo "bad" ;;
[0-9]*[hmd] ) echo "good" ;;
* ) echo "bad" ;;
esac

i.e. rather than explicitly specifying every bad pattern, just specify
up front those bad patterns that are a subset of the potentially good
patterns, then specify the good pattern(s), then let the final "*" catch
all other bad patterns.

Regards,

Ed.

Re: how to test for user input

am 09.01.2008 17:26:35 von littlehelphere

On Jan 8, 6:45 pm, Ed Morton wrote:
> littlehelph...@gmail.com wrote:
> > On Jan 8, 4:44 pm, Ed Morton wrote:
>
> >>littlehelph...@gmail.com wrote:
>
> >>> I have a script and part of requires input from the user for time in
> >>>the form of h(hours), m(minutes) or d(days)
> >>>for example 1d eqautes to 1 day.
> >>> I would like to set up a test in ksh to verify the input is in
> >>>fact a numeric value followed by one of the letters above. Basically
> >>>if a user enter 1f I want the script to ask for input again. If the
> >>>user enters 1m then the script should go on. I understand this is a
> >>>if then statement but I cannot get what to test for. I have tried the
> >>>"||" but no luck. Thanks in advance.
>
> >>Not, it's not an "if" statement, it's a "case" statement:
>
> >>read time
> >>case $time in
> >> [0-9]*[hmd] ) echo "good" ;;
> >> * ) echo "bad" ;;
> >>esac
>
> >>Regards,
>
> >> Ed.
>
> > Thanks - two quick questions
> > 1) How do I set this up so if the test fails the user is forced to
> > enter a valid response?
>
> time=""
> while [ -z "$time" ]
> do
> printf "Enter a time in \"[0-9]*[hmd]\" format: " >&2
> IFS= read -r time
> case $time in
> [0-9]*[hmd] ) : ;;
> * ) printf "Invalid time \"%s\", try again.\n" "$time" >&2
> time=""
> ;;
> esac
> done
>
> > 2) Could this be an if/then statement or in a case like this is a case
> > statement the "best practice"?
>
> I wouldn't even think of trying that with an if/then. "case" is best
> practice.
>
> Ed.

That did it thanks - now this brings me to another question on using
the case script. Can I use a variable for a response. For example
lets say I want the operator to enter a valid user from a file such as
the passwd file.


Would something like this work? Thanks.
user=""
while [ -z "$user" ]
do
foobar=`awk -F: '{print $1}' /etc/passwd`
printf "valid users are $foobar - please enter one:" >&2
case $userin
$foobar) : ;;
*) printf "Invalid user \"%s\", try again.\n" "$user" >&2
user=""
;;
esac
done

Re: how to test for user input

am 09.01.2008 18:23:15 von Ed Morton

littlehelphere@gmail.com wrote:
> On Jan 8, 6:45 pm, Ed Morton wrote:
>
>>littlehelph...@gmail.com wrote:
>>
>>>On Jan 8, 4:44 pm, Ed Morton wrote:
>>
>>>>littlehelph...@gmail.com wrote:
>>
>>>>> I have a script and part of requires input from the user for time in
>>>>>the form of h(hours), m(minutes) or d(days)
>>>>>for example 1d eqautes to 1 day.
>>>>> I would like to set up a test in ksh to verify the input is in
>>>>>fact a numeric value followed by one of the letters above. Basically
>>>>>if a user enter 1f I want the script to ask for input again. If the
>>>>>user enters 1m then the script should go on. I understand this is a
>>>>>if then statement but I cannot get what to test for. I have tried the
>>>>>"||" but no luck. Thanks in advance.
>>
>>>>Not, it's not an "if" statement, it's a "case" statement:
>>
>>>>read time
>>>>case $time in
>>>> [0-9]*[hmd] ) echo "good" ;;
>>>> * ) echo "bad" ;;
>>>>esac
>>
>>>>Regards,
>>
>>>> Ed.
>>
>>>Thanks - two quick questions
>>>1) How do I set this up so if the test fails the user is forced to
>>>enter a valid response?
>>
>>time=""
>>while [ -z "$time" ]
>>do
>> printf "Enter a time in \"[0-9]*[hmd]\" format: " >&2
>> IFS= read -r time
>> case $time in
>> [0-9]*[hmd] ) : ;;
>> * ) printf "Invalid time \"%s\", try again.\n" "$time" >&2
>> time=""
>> ;;
>> esac
>>done
>>
>>
>>>2) Could this be an if/then statement or in a case like this is a case
>>>statement the "best practice"?
>>
>>I wouldn't even think of trying that with an if/then. "case" is best
>>practice.
>>
>> Ed.
>
>
> That did it thanks

Please check the other part of this thread where Stephane points out the
hole and we discuss fixes.

> - now this brings me to another question on using
> the case script. Can I use a variable for a response. For example
> lets say I want the operator to enter a valid user from a file such as
> the passwd file.
>
>
> Would something like this work? Thanks.
> user=""
> while [ -z "$user" ]
> do
> foobar=`awk -F: '{print $1}' /etc/passwd`
> printf "valid users are $foobar - please enter one:" >&2
> case $userin
> $foobar) : ;;
> *) printf "Invalid user \"%s\", try again.\n" "$user" >&2
> user=""
> ;;
> esac
> done
>
>

I'd do that as:

user=""
sep=" "
foobar=`awk -F: -v sep="$sep" '{print sep $1 sep}' /etc/passwd`
while [ -z "$user" ]
do
printf "valid users are:\n%s\nplease enter one: " "$foobar" >&2
IFS= read -r user
case $foobar in
*${sep}${user}${sep}* ) echo "good" ;;
* ) echo "bad"; user="" ;;
esac
done

i.e. match the list against the specific value entered rather than
trying to find the value entered in the list (which would require a grep).

Regards,

Ed.

Re: how to test for user input

am 09.01.2008 18:26:23 von Ed Morton

Ed Morton wrote:

> littlehelphere@gmail.com wrote:
>
>> On Jan 8, 6:45 pm, Ed Morton wrote:
>>
>>> littlehelph...@gmail.com wrote:
>>>
>>>> On Jan 8, 4:44 pm, Ed Morton wrote:
>>>
>>>
>>>>> littlehelph...@gmail.com wrote:
>>>
>>>
>>>>>> I have a script and part of requires input from the user for time in
>>>>>> the form of h(hours), m(minutes) or d(days)
>>>>>> for example 1d eqautes to 1 day.
>>>>>> I would like to set up a test in ksh to verify the input is in
>>>>>> fact a numeric value followed by one of the letters above. Basically
>>>>>> if a user enter 1f I want the script to ask for input again. If the
>>>>>> user enters 1m then the script should go on. I understand this is a
>>>>>> if then statement but I cannot get what to test for. I have tried
>>>>>> the
>>>>>> "||" but no luck. Thanks in advance.
>>>
>>>
>>>>> Not, it's not an "if" statement, it's a "case" statement:
>>>
>>>
>>>>> read time
>>>>> case $time in
>>>>> [0-9]*[hmd] ) echo "good" ;;
>>>>> * ) echo "bad" ;;
>>>>> esac
>>>
>>>
>>>>> Regards,
>>>
>>>
>>>>> Ed.
>>>
>>>
>>>> Thanks - two quick questions
>>>> 1) How do I set this up so if the test fails the user is forced to
>>>> enter a valid response?
>>>
>>>
>>> time=""
>>> while [ -z "$time" ]
>>> do
>>> printf "Enter a time in \"[0-9]*[hmd]\" format: " >&2
>>> IFS= read -r time
>>> case $time in
>>> [0-9]*[hmd] ) : ;;
>>> * ) printf "Invalid time \"%s\", try again.\n" "$time" >&2
>>> time=""
>>> ;;
>>> esac
>>> done
>>>
>>>
>>>> 2) Could this be an if/then statement or in a case like this is a case
>>>> statement the "best practice"?
>>>
>>>
>>> I wouldn't even think of trying that with an if/then. "case" is best
>>> practice.
>>>
>>> Ed.
>>
>>
>>
>> That did it thanks
>
>
> Please check the other part of this thread where Stephane points out the
> hole and we discuss fixes.
>
>> - now this brings me to another question on using
>> the case script. Can I use a variable for a response. For example
>> lets say I want the operator to enter a valid user from a file such as
>> the passwd file.
>>
>>
>> Would something like this work? Thanks.
>> user=""
>> while [ -z "$user" ]
>> do
>> foobar=`awk -F: '{print $1}' /etc/passwd`
>> printf "valid users are $foobar - please enter one:" >&2
>> case $userin
>> $foobar) : ;;
>> *) printf "Invalid user \"%s\", try again.\n" "$user" >&2
>> user=""
>> ;;
>> esac
>> done
>>
>>
>
> I'd do that as:
>
> user=""
> sep=" "
> foobar=`awk -F: -v sep="$sep" '{print sep $1 sep}' /etc/passwd`
> while [ -z "$user" ]
> do
> printf "valid users are:\n%s\nplease enter one: " "$foobar" >&2
> IFS= read -r user
> case $foobar in
> *${sep}${user}${sep}* ) echo "good" ;;
> * ) echo "bad"; user="" ;;
> esac
> done
>
> i.e. match the list against the specific value entered rather than
> trying to find the value entered in the list (which would require a grep).
>
> Regards,
>
> Ed.

Caveat - this will give false positives if the user enters globbing wild
cards such as "*". A better approach is probably to offer a numbered
list of names and ask the users to enter the corresponding number rather
than typing the full name.

Ed.

Re: how to test for user input

am 09.01.2008 18:54:26 von Icarus Sparry

On Wed, 09 Jan 2008 11:26:23 -0600, Ed Morton wrote:

> Ed Morton wrote:
>
>> littlehelphere@gmail.com wrote:
>>
>>> On Jan 8, 6:45 pm, Ed Morton wrote:
>>>
>>>> littlehelph...@gmail.com wrote:
>>>>
>>>>> On Jan 8, 4:44 pm, Ed Morton wrote:
>>>>
>>>>
>>>>>> littlehelph...@gmail.com wrote:

>>> - now this brings me to another question on using the case script.
>>> Can I use a variable for a response. For example lets say I want the
>>> operator to enter a valid user from a file such as the passwd file.
>>>
>>>
>>> Would something like this work? Thanks. user=""
>>> while [ -z "$user" ]
>>> do
>>> foobar=`awk -F: '{print $1}' /etc/passwd` printf "valid users are
>>> $foobar - please enter one:" >&2 case $userin
>>> $foobar) : ;;
>>> *) printf "Invalid user \"%s\", try again.\n" "$user" >&2 user=""
>>> ;;
>>> esac
>>> done
>>>
>>>
>>>
>> I'd do that as:
>>
>> user=""
>> sep=" "
>> foobar=`awk -F: -v sep="$sep" '{print sep $1 sep}' /etc/passwd` while [
>> -z "$user" ]
>> do
>> printf "valid users are:\n%s\nplease enter one: " "$foobar" >&2
>> IFS= read -r user
>> case $foobar in
>> *${sep}${user}${sep}* ) echo "good" ;; * ) echo
>> "bad"; user="" ;; esac
>> done
>>
>> i.e. match the list against the specific value entered rather than
>> trying to find the value entered in the list (which would require a
>> grep).
>>
>> Regards,
>>
>> Ed.
>
> Caveat - this will give false positives if the user enters globbing wild
> cards such as "*". A better approach is probably to offer a numbered
> list of names and ask the users to enter the corresponding number rather
> than typing the full name.
>
> Ed.

And the correct way to do this is with a "select" statement.
user=""
validusers=$( sed 's/:.*//' /etc/passwd)
PS3='Enter a number, or 0 to abort'
select user in $validusers
do
echo "user is '$user', REPLY is '$REPLY'"
if [ 0 = "$REPLY" ] ; then break ; fi
case "$user" in
"") continue;;
*) break ;;
esac
done

Re: how to test for user input

am 09.01.2008 20:09:49 von littlehelphere

On Jan 9, 12:54 pm, Icarus Sparry wrote:
> On Wed, 09 Jan 2008 11:26:23 -0600, Ed Morton wrote:
> > Ed Morton wrote:
>
> >> littlehelph...@gmail.com wrote:
>
> >>> On Jan 8, 6:45 pm, Ed Morton wrote:
>
> >>>> littlehelph...@gmail.com wrote:
>
> >>>>> On Jan 8, 4:44 pm, Ed Morton wrote:
>
> >>>>>> littlehelph...@gmail.com wrote:
> >>> - now this brings me to another question on using the case script.
> >>> Can I use a variable for a response. For example lets say I want the
> >>> operator to enter a valid user from a file such as the passwd file.
>
> >>> Would something like this work? Thanks. user=""
> >>> while [ -z "$user" ]
> >>> do
> >>> foobar=`awk -F: '{print $1}' /etc/passwd` printf "valid users are
> >>> $foobar - please enter one:" >&2 case $userin
> >>> $foobar) : ;;
> >>> *) printf "Invalid user \"%s\", try again.\n" "$user" >&2 user=""
> >>> ;;
> >>> esac
> >>> done
>
> >> I'd do that as:
>
> >> user=""
> >> sep=" "
> >> foobar=`awk -F: -v sep="$sep" '{print sep $1 sep}' /etc/passwd` while [
> >> -z "$user" ]
> >> do
> >> printf "valid users are:\n%s\nplease enter one: " "$foobar" >&2
> >> IFS= read -r user
> >> case $foobar in
> >> *${sep}${user}${sep}* ) echo "good" ;; * ) echo
> >> "bad"; user="" ;; esac
> >> done
>
> >> i.e. match the list against the specific value entered rather than
> >> trying to find the value entered in the list (which would require a
> >> grep).
>
> >> Regards,
>
> >> Ed.
>
> > Caveat - this will give false positives if the user enters globbing wild
> > cards such as "*". A better approach is probably to offer a numbered
> > list of names and ask the users to enter the corresponding number rather
> > than typing the full name.
>
> > Ed.
>
> And the correct way to do this is with a "select" statement.
> user=""
> validusers=$( sed 's/:.*//' /etc/passwd)
> PS3='Enter a number, or 0 to abort'
> select user in $validusers
> do
> echo "user is '$user', REPLY is '$REPLY'"
> if [ 0 = "$REPLY" ] ; then break ; fi
> case "$user" in
> "") continue;;
> *) break ;;
> esac
> done

OK - I went through the code and ran it an understand the concept.
However, I am having some difficulty in implementing it. Here is my
situation.

I have a flat file containing a hostname with service
ie -
for host alpha
alpha.cpu
alpha.memory
alpha.io
......
I go through the file and strip of the hostname leaving only the
available services. I then want the user to choose one service to get
details. I tried the following and while the output, etc is in place
the check does not seem to be working. Regardless of the info entered
it moves on to next step
....
service=""
SERVICE=`ls -1 /path_to_file/$server.* | awk -F\/ '{print $NF}'| awk -
F. '{print $2}'` #(this gets the info per host)
while [ -z "$service" ]
do
echo
echo "******Please choose a service:*****
$SERVICE
You may also choose all as well"
printf "Enter a valid service: " >&2
IFS= read -r service
case $service in
${SERVICE} ) : ;;
* ) printf "Invalid service \"%s\", try again.\n" "$service" >&2
service=""
;;
esac
done
....

Thanks once again. Also, can you provide a brief explanation on
what I am doing wrong here - for my own benefit.

Re: how to test for user input

am 09.01.2008 21:26:04 von littlehelphere

On Jan 9, 2:09 pm, littlehelph...@gmail.com wrote:
> On Jan 9, 12:54 pm, Icarus Sparry wrote:
>
>
>
> > On Wed, 09 Jan 2008 11:26:23 -0600, Ed Morton wrote:
> > > Ed Morton wrote:
>
> > >> littlehelph...@gmail.com wrote:
>
> > >>> On Jan 8, 6:45 pm, Ed Morton wrote:
>
> > >>>> littlehelph...@gmail.com wrote:
>
> > >>>>> On Jan 8, 4:44 pm, Ed Morton wrote:
>
> > >>>>>> littlehelph...@gmail.com wrote:
> > >>> - now this brings me to another question on using the case script.
> > >>> Can I use a variable for a response. For example lets say I want the
> > >>> operator to enter a valid user from a file such as the passwd file.
>
> > >>> Would something like this work? Thanks. user=""
> > >>> while [ -z "$user" ]
> > >>> do
> > >>> foobar=`awk -F: '{print $1}' /etc/passwd` printf "valid users are
> > >>> $foobar - please enter one:" >&2 case $userin
> > >>> $foobar) : ;;
> > >>> *) printf "Invalid user \"%s\", try again.\n" "$user" >&2 user=""
> > >>> ;;
> > >>> esac
> > >>> done
>
> > >> I'd do that as:
>
> > >> user=""
> > >> sep=" "
> > >> foobar=`awk -F: -v sep="$sep" '{print sep $1 sep}' /etc/passwd` while [
> > >> -z "$user" ]
> > >> do
> > >> printf "valid users are:\n%s\nplease enter one: " "$foobar" >&2
> > >> IFS= read -r user
> > >> case $foobar in
> > >> *${sep}${user}${sep}* ) echo "good" ;; * ) echo
> > >> "bad"; user="" ;; esac
> > >> done
>
> > >> i.e. match the list against the specific value entered rather than
> > >> trying to find the value entered in the list (which would require a
> > >> grep).
>
> > >> Regards,
>
> > >> Ed.
>
> > > Caveat - this will give false positives if the user enters globbing wild
> > > cards such as "*". A better approach is probably to offer a numbered
> > > list of names and ask the users to enter the corresponding number rather
> > > than typing the full name.
>
> > > Ed.
>
> > And the correct way to do this is with a "select" statement.
> > user=""
> > validusers=$( sed 's/:.*//' /etc/passwd)
> > PS3='Enter a number, or 0 to abort'
> > select user in $validusers
> > do
> > echo "user is '$user', REPLY is '$REPLY'"
> > if [ 0 = "$REPLY" ] ; then break ; fi
> > case "$user" in
> > "") continue;;
> > *) break ;;
> > esac
> > done
>
> OK - I went through the code and ran it an understand the concept.
> However, I am having some difficulty in implementing it. Here is my
> situation.
>
> I have a flat file containing a hostname with service
> ie -
> for host alpha
> alpha.cpu
> alpha.memory
> alpha.io
> .....
> I go through the file and strip of the hostname leaving only the
> available services. I then want the user to choose one service to get
> details. I tried the following and while the output, etc is in place
> the check does not seem to be working. Regardless of the info entered
> it moves on to next step
> ...
> service=""
> SERVICE=`ls -1 /path_to_file/$server.* | awk -F\/ '{print $NF}'| awk -
> F. '{print $2}'` #(this gets the info per host)
> while [ -z "$service" ]
> do
> echo
> echo "******Please choose a service:*****
> $SERVICE
> You may also choose all as well"
> printf "Enter a valid service: " >&2
> IFS= read -r service
> case $service in
> ${SERVICE} ) : ;;
> * ) printf "Invalid service \"%s\", try again.\n" "$service" >&2
> service=""
> ;;
> esac
> done
> ...
>
> Thanks once again. Also, can you provide a brief explanation on
> what I am doing wrong here - for my own benefit.

Oh one other thing I would like the operator to be able to pick
multiple options, or an all option as well.

Re: how to test for user input

am 09.01.2008 21:52:51 von littlehelphere

On Jan 9, 3:26 pm, littlehelph...@gmail.com wrote:
> On Jan 9, 2:09 pm, littlehelph...@gmail.com wrote:
>
>
>
> > On Jan 9, 12:54 pm, Icarus Sparry wrote:
>
> > > On Wed, 09 Jan 2008 11:26:23 -0600, Ed Morton wrote:
> > > > Ed Morton wrote:
>
> > > >> littlehelph...@gmail.com wrote:
>
> > > >>> On Jan 8, 6:45 pm, Ed Morton wrote:
>
> > > >>>> littlehelph...@gmail.com wrote:
>
> > > >>>>> On Jan 8, 4:44 pm, Ed Morton wrote:
>
> > > >>>>>> littlehelph...@gmail.com wrote:
> > > >>> - now this brings me to another question on using the case script.
> > > >>> Can I use a variable for a response. For example lets say I want the
> > > >>> operator to enter a valid user from a file such as the passwd file.
>
> > > >>> Would something like this work? Thanks. user=""
> > > >>> while [ -z "$user" ]
> > > >>> do
> > > >>> foobar=`awk -F: '{print $1}' /etc/passwd` printf "valid users are
> > > >>> $foobar - please enter one:" >&2 case $userin
> > > >>> $foobar) : ;;
> > > >>> *) printf "Invalid user \"%s\", try again.\n" "$user" >&2 user=""
> > > >>> ;;
> > > >>> esac
> > > >>> done
>
> > > >> I'd do that as:
>
> > > >> user=""
> > > >> sep=" "
> > > >> foobar=`awk -F: -v sep="$sep" '{print sep $1 sep}' /etc/passwd` while [
> > > >> -z "$user" ]
> > > >> do
> > > >> printf "valid users are:\n%s\nplease enter one: " "$foobar" >&2
> > > >> IFS= read -r user
> > > >> case $foobar in
> > > >> *${sep}${user}${sep}* ) echo "good" ;; * ) echo
> > > >> "bad"; user="" ;; esac
> > > >> done
>
> > > >> i.e. match the list against the specific value entered rather than
> > > >> trying to find the value entered in the list (which would require a
> > > >> grep).
>
> > > >> Regards,
>
> > > >> Ed.
>
> > > > Caveat - this will give false positives if the user enters globbing wild
> > > > cards such as "*". A better approach is probably to offer a numbered
> > > > list of names and ask the users to enter the corresponding number rather
> > > > than typing the full name.
>
> > > > Ed.
>
> > > And the correct way to do this is with a "select" statement.
> > > user=""
> > > validusers=$( sed 's/:.*//' /etc/passwd)
> > > PS3='Enter a number, or 0 to abort'
> > > select user in $validusers
> > > do
> > > echo "user is '$user', REPLY is '$REPLY'"
> > > if [ 0 = "$REPLY" ] ; then break ; fi
> > > case "$user" in
> > > "") continue;;
> > > *) break ;;
> > > esac
> > > done
>
> > OK - I went through the code and ran it an understand the concept.
> > However, I am having some difficulty in implementing it. Here is my
> > situation.
>
> > I have a flat file containing a hostname with service
> > ie -
> > for host alpha
> > alpha.cpu
> > alpha.memory
> > alpha.io
> > .....
> > I go through the file and strip of the hostname leaving only the
> > available services. I then want the user to choose one service to get
> > details. I tried the following and while the output, etc is in place
> > the check does not seem to be working. Regardless of the info entered
> > it moves on to next step
> > ...
> > service=""
> > SERVICE=`ls -1 /path_to_file/$server.* | awk -F\/ '{print $NF}'| awk -
> > F. '{print $2}'` #(this gets the info per host)
> > while [ -z "$service" ]
> > do
> > echo
> > echo "******Please choose a service:*****
> > $SERVICE
> > You may also choose all as well"
> > printf "Enter a valid service: " >&2
> > IFS= read -r service
> > case $service in
> > ${SERVICE} ) : ;;
> > * ) printf "Invalid service \"%s\", try again.\n" "$service" >&2
> > service=""
> > ;;
> > esac
> > done
> > ...
>
> > Thanks once again. Also, can you provide a brief explanation on
> > what I am doing wrong here - for my own benefit.
>
> Oh one other thing I would like the operator to be able to pick
> multiple options, or an all option as well.

Ok I think I got it to work. Just doing some last minute testing.
Thank you all for your help. Also, if you still would like to answer
the question I would like to see everyones approach to the problem and
see how I stacked up. Thanks again.

Re: how to test for user input

am 09.01.2008 23:29:10 von Ed Morton

littlehelphere@gmail.com wrote:
> On Jan 9, 3:26 pm, littlehelph...@gmail.com wrote:
>
>>On Jan 9, 2:09 pm, littlehelph...@gmail.com wrote:
>>
>>
>>
>>
>>>On Jan 9, 12:54 pm, Icarus Sparry wrote:
>>
>>>>On Wed, 09 Jan 2008 11:26:23 -0600, Ed Morton wrote:
>>>>
>>>>>Ed Morton wrote:
>>
>>>>>>littlehelph...@gmail.com wrote:
>>
>>>>>>>On Jan 8, 6:45 pm, Ed Morton wrote:
>>
>>>>>>>>littlehelph...@gmail.com wrote:
>>
>>>>>>>>>On Jan 8, 4:44 pm, Ed Morton wrote:
>>
>>>>>>>>>>littlehelph...@gmail.com wrote:
>>>>>>>
>>>>>>>- now this brings me to another question on using the case script.
>>>>>>>Can I use a variable for a response. For example lets say I want the
>>>>>>>operator to enter a valid user from a file such as the passwd file.
>>
>>>>>>>Would something like this work? Thanks. user=""
>>>>>>>while [ -z "$user" ]
>>>>>>>do
>>>>>>>foobar=`awk -F: '{print $1}' /etc/passwd` printf "valid users are
>>>>>>>$foobar - please enter one:" >&2 case $userin
>>>>>>>$foobar) : ;;
>>>>>>>*) printf "Invalid user \"%s\", try again.\n" "$user" >&2 user=""
>>>>>>>;;
>>>>>>>esac
>>>>>>>done
>>
>>>>>>I'd do that as:
>>
>>>>>>user=""
>>>>>>sep=" "
>>>>>>foobar=`awk -F: -v sep="$sep" '{print sep $1 sep}' /etc/passwd` while [
>>>>>>-z "$user" ]
>>>>>>do
>>>>>> printf "valid users are:\n%s\nplease enter one: " "$foobar" >&2
>>>>>> IFS= read -r user
>>>>>> case $foobar in
>>>>>> *${sep}${user}${sep}* ) echo "good" ;; * ) echo
>>>>>> "bad"; user="" ;; esac
>>>>>>done
>>
>>>>>>i.e. match the list against the specific value entered rather than
>>>>>>trying to find the value entered in the list (which would require a
>>>>>>grep).
>>
>>>>>>Regards,
>>
>>>>>> Ed.
>>
>>>>>Caveat - this will give false positives if the user enters globbing wild
>>>>>cards such as "*". A better approach is probably to offer a numbered
>>>>>list of names and ask the users to enter the corresponding number rather
>>>>>than typing the full name.
>>
>>>>> Ed.
>>
>>>>And the correct way to do this is with a "select" statement.
>>>>user=""
>>>>validusers=$( sed 's/:.*//' /etc/passwd)

I suppose we should really just be using

cut -d: -f1 /etc/passwd

for that part.

>>>>PS3='Enter a number, or 0 to abort'
>>>>select user in $validusers
>>>>do
>>>> echo "user is '$user', REPLY is '$REPLY'"
>>>> if [ 0 = "$REPLY" ] ; then break ; fi
>>>> case "$user" in
>>>> "") continue;;
>>>> *) break ;;
>>>> esac
>>>>done

Hmm, never used select. It does look like an easy option for this
application.

>>>OK - I went through the code and ran it an understand the concept.
>>>However, I am having some difficulty in implementing it. Here is my
>>>situation.
>>
>>>I have a flat file containing a hostname with service
>>>ie -
>>>for host alpha
>>>alpha.cpu
>>>alpha.memory
>>>alpha.io
>>>.....
>>>I go through the file and strip of the hostname leaving only the
>>>available services. I then want the user to choose one service to get
>>>details. I tried the following and while the output, etc is in place
>>>the check does not seem to be working. Regardless of the info entered
>>>it moves on to next step
>>>...
>>>service=""
>>>SERVICE=`ls -1 /path_to_file/$server.* | awk -F\/ '{print $NF}'| awk -
>>>F. '{print $2}'` #(this gets the info per host)
>>>while [ -z "$service" ]
>>>do
>>>echo
>>>echo "******Please choose a service:*****
>>>$SERVICE
>>>You may also choose all as well"
>>>printf "Enter a valid service: " >&2
>>>IFS= read -r service
>>>case $service in
>>>${SERVICE} ) : ;;
>>>* ) printf "Invalid service \"%s\", try again.\n" "$service" >&2
>>>service=""
>>>;;
>>>esac
>>>done
>>>...
>>
>>> Thanks once again. Also, can you provide a brief explanation on
>>>what I am doing wrong here - for my own benefit.
>>
>>Oh one other thing I would like the operator to be able to pick
>>multiple options, or an all option as well.
>
>
> Ok I think I got it to work. Just doing some last minute testing.
> Thank you all for your help. Also, if you still would like to answer
> the question I would like to see everyones approach to the problem and
> see how I stacked up. Thanks again.

I think the question you're refering to is "can you provide a brief
explanation on what I am doing wrong here". The main problem I saw in
your script was that you were still doing

case $item in
$list ) ...
esac

instead of:

case $list in
$item esac

Also, the initial assignment to SERVICE:

> SERVICE=`ls -1 /path_to_file/$server.* | awk -F\/ '{print $NF}'| awk -F. '{print $2}'`

doesn't seem to reflect the preceeding text:

> I have a flat file containing a hostname with service

so I'm not sure what the real intent is there. Maybe you should post
just your real application with the current script your using.

Ed.

Re: how to test for user input

am 10.01.2008 07:33:38 von Icarus Sparry

On Wed, 09 Jan 2008 12:26:04 -0800, littlehelphere wrote:

> On Jan 9, 2:09 pm, littlehelph...@gmail.com wrote:
>> On Jan 9, 12:54 pm, Icarus Sparry wrote:

>> > And the correct way to do this is with a "select" statement. user=""
>> > validusers=$( sed 's/:.*//' /etc/passwd) PS3='Enter a number, or 0 to
>> > abort'
>> > select user in $validusers
>> > do
>> > echo "user is '$user', REPLY is '$REPLY'" if [ 0 = "$REPLY" ]
>> > ; then break ; fi case "$user" in
>> > "") continue;;
>> > *) break ;;
>> > esac
>> > done
>>
>> OK - I went through the code and ran it an understand the concept.
>> However, I am having some difficulty in implementing it. Here is my
>> situation.
>>
>> I have a flat file containing a hostname with service ie -
>> for host alpha
>> alpha.cpu
>> alpha.memory
>> alpha.io
>> .....
>> I go through the file and strip of the hostname leaving only the
>> available services. I then want the user to choose one service to get
>> details. I tried the following and while the output, etc is in place
>> the check does not seem to be working. Regardless of the info entered
>> it moves on to next step
>> ...
>> service=""
>> SERVICE=`ls -1 /path_to_file/$server.* | awk -F\/ '{print $NF}'|
>> awk -F. '{print $2}'`
>> #(this gets the info per host) while [ -z "$service" ]
>> do
>> echo
>> echo "******Please choose a service:***** $SERVICE
>> You may also choose all as well"
>> printf "Enter a valid service: " >&2
>> IFS= read -r service
>> case $service in
>> ${SERVICE} ) : ;;
>> * ) printf "Invalid service \"%s\", try again.\n" "$service" >&2
>> service=""
>> ;;
>> esac
>> done
>> ...
>>
>> Thanks once again. Also, can you provide a brief explanation on
>> what I am doing wrong here - for my own benefit.
>
> Oh one other thing I would like the operator to be able to pick multiple
> options, or an all option as well.

Select is rather orientated to picking a single option at a time,
although it has an implicit loop. It is easy to add an "all" option, just
add it on the end of the list.

Once you have your variable with a list of services in it, e.g. SERVICES,
you can write something like

PS3="Choose the number of the next service you would like to add"
select s in all $SERVICES end
do
case $s in
all) services=$SERVICES ; break ;;
end) break ;;
"") echo "invalid response '$REPLY'" ;;
*) services="$services $s" ;;
esac
done

At this point you have a list of services chosen in the "$services"
variable, with a leading space if they were selected one by one.

You can alter PS3 in the loop to show what you already have if you want.