1

Is there a way to validate or confirm that the user wrote what it meant to write in read?

  • For example, the user meant to write "Hello world!" but mistakenly wrote "Hello world@".

  • This is very similar to contact-form validation of an email / phone field.

Is there a way to prompt the user with something like "Please retype the input", in read?

I found no such option in man read.


Note: The input is a password so I don't want to print or compare it with an already existing string.

3
  • If you want to confirm every time, just read twice, perhaps with a printf in between to tell them you are doing so
    – Fox
    Jan 13, 2018 at 9:15
  • Sorry for not mentioning, this data is sensitive so I avoid printing. I've edited the question. I assume that read twice doesn't make sure the second input is identical to the first. Jan 13, 2018 at 9:23
  • It does if you read to different variables and compare them — and then either exit or loop back (with a message?) if they don't match
    – Fox
    Jan 13, 2018 at 9:57

2 Answers 2

4

With the bash shell, you can always do

FOO=a
BAR=b
prompt="Please enter value twice for validation"
while [[ "$FOO" != "$BAR" ]]; do
    echo -e $prompt
    read -s -p "Enter value: " FOO
    read -s -p "Retype to validate: " BAR
    prompt="\nUups, please try again"
done
unset -v BAR
# do whatever you need to do with FOO
unset -v FOO

read options used:

  • -s Silent mode. If input is coming from a terminal, characters are not echoed.
  • -p prompt Display prompt on standard error, without a trailing newline, before attempting to read any input.
3
  • What's read -p? I didn't find a man entry. Jan 13, 2018 at 11:09
  • 1
    @Arcticooling Try man bash :-)
    – nohillside
    Jan 13, 2018 at 11:13
  • 2
    @Arcticooling In bash, the manual for individual built-in commands is also available using e.g. help read.
    – Kusalananda
    Jan 13, 2018 at 13:59
3

You could define a function for that.

With zsh or bash:

blind_read_and_confirm() {
  # args: <prompt> <variable-name>
  local _confirm_
  until
    printf >&2 %s "$1"
    IFS= read -rs "${2-REPLY}" || return
    printf >&2 "\n%*s" "${#1}" 'and again: '
    IFS= read -rs _confirm_ || return
    eval '[ "${'"${2-REPLY}"'}" = "$_confirm_" ]'
  do
    printf >&2 "\nEntries differ, please try again.\n"
  done
  printf '\n'
}

To be used for instance as

blind_read_and_confirm "Please choose a password: " password || exit

printf 'You entered a %s character password.\n' "${#password}"

Note that without the IFS= and -r, if the user entered " \/ery secret ", "/ery secret" would be stored in $password.

2
  • I suppose in Bash or ksh we could do without the eval with a nameref
    – ilkkachu
    Jan 14, 2018 at 18:30
  • @ilkkachu, yes, though only ksh93 does real namerefs. For instance, with bash that still wouldn't allow blink_read_and_confirm prompt _confirm_. In bash, that's just cosmetic sugar over eval, so you might as well use ${!2} (like ${(P)2} in zsh) Jan 14, 2018 at 18:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .