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.

  • 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 '18 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. – Arcticooling Jan 13 '18 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 '18 at 9:57

With the bash shell, you can always do

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"
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.
  • What's read -p? I didn't find a man entry. – Arcticooling Jan 13 '18 at 11:09
  • 1
    @Arcticooling Try man bash :-) – nohillside Jan 13 '18 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 '18 at 13:59

You could define a function for that.

With zsh or bash:

blind_read_and_confirm() {
  # args: <prompt> <variable-name>
  local _confirm_
    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_" ]'
    printf >&2 "\nEntries differ, please try again.\n"
  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.

  • I suppose in Bash or ksh we could do without the eval with a nameref – ilkkachu Jan 14 '18 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) – Stéphane Chazelas Jan 14 '18 at 18:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.