neandertalc has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I wrote a script that takes user input for confirmation. Now, I want that the "default" option will be yes, the "y" will already be ready there, in the STDIN ("Are you sure? y" will be the output). I tried something like print STDIN "y"; but of course that didn't do any good, does anyone know how to do that?

Replies are listed 'Best First'.
Re: writing to stdin
by ambs (Pilgrim) on Mar 28, 2005 at 12:43 UTC
    Well.. try something like:
    print "Are you sure? [y]"; chomp(my $ans = <STDIN>); $ans ||= "y"; if ($ans =~ m!^y(es)?!) { # do something } else { # do otherthing }

    Update: added missing chomp thanks to cog. Added some more code as asked by virtualsue.

    Alberto Simões

      There are two problems with the code...

      First, it's not case-insensitive...

      Secondly, an answer such as "y should I?" will match :-)

      This will do the trick:

      print "Are you sure? [y]"; chomp(my $ans = <STDIN>); $ans ||= "y"; if ($ans =~ m!^y(es)?$!i) { # do something } else { # do otherthing }

      And another approach:

      #!/usr/bin/perl print "Are you sure? [y]"; if (<> =~ /^(y(es)?)?\n$/i) { # answer was yes } else { # answer was no }
      Actually, there's a chomp $ans; missing (otherwise, one could write my $ans = <STDIN> || 'y';, which would be quite cool...)
      Other than the chomp problem, this code will interpret the answer "yes" as no. Maybe this is trivial, but I think it's nice to make the extra effort to do what the user really wants. :-)
Re: writing to stdin
by virtualsue (Vicar) on Mar 28, 2005 at 13:19 UTC
    Here's one way to allow a user a lot of latitude in answering a yes/no question. This allows any answer other than one beginning with n or N to be interpreted as "yes".
    print "Are you sure? [y]"; my $ans = <STDIN>; if ($ans !~ /^n/i) { print "Yes\n"; } else { print "Nope\n"; }
Re: writing to stdin
by merlyn (Sage) on Mar 28, 2005 at 17:43 UTC
    If you're looking to "pretend" the user has typed a "y", so that she has to back up over it if she wants to change her mind, I'd first consider that to be pretty rude behavior by a program. The normal trick is to accept an empty entry as you would a "y", and show the default as part of the prompt.

    However, if you're dead-set committed to pre-typing something for the user, and you're on Unix, you can use the TIOCSTI ioctl to force things into the input terminal (of course, this does nothing for piped or file input). Google around for Perl and TIOCSTI to see some sample code.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: writing to stdin
by samizdat (Vicar) on Mar 28, 2005 at 14:09 UTC
    The code already offered is excellent, but I'd like to address the conceptual bug in your understanding. On a UN!X machine, i.e. FreeBSD, Linux, Solaris, et al, STDIN and STDOUT are both connected to the console unless they are connected to pipes (or otherwise redirected). STDIN accepts what you type (which is also echoed automatically to STDOUT), and STDOUT prints what your program spits out. In other words, to put stuff on your console, you print 'stuff';, which can also be written as print STDOUT 'stuff';.

    HTH :D
      If you used to program with lex or flex you would notice that the question is not so weird. In fact, it is common to use 'unput' to put characters back in the input buffer (which in fact can be from stdin).

      Ok, I know flex does not push it into stdin, but it gives you that idea.

      Cheers

      Alberto Simões

        Aye, but we be dealin' wit a newbie here, to be sure. You be absolutely correct in ta wunderful complexity of te entire UN!X worlt, but let's not be confusin te poor bairn right from t'start. :D
Re: writing to stdin
by marinersk (Priest) on Mar 28, 2005 at 18:07 UTC
    I like:
    use strict; my $ansflg = 0; while (!$ansflg) { # No valid answer received yet print "Confirm [Y,n]: "; my $geninp = <STDIN>; chomp $geninp; if ($geninp =~ /^\s*$/) { # Blank answer means DEFAULT $geninp = 'Y'; } my $genexp = quotemeta $geninp; if ("YES" =~ /^$genexp/i) { # Said YES print "Answer = YES\n"; $ansflg = 1; } elsif ("NO" =~ /^$genexp/i) { # Said NO print "Answer = NO\n"; $ansflg = 1; } else { # Said something else # Do nothing; repeat the prompt } } exit;
    This permits upper- or lowercase, Y, YE, YES, or a blank answer to be taken as a YES, while N and NO mean NO, and invalid answers don't slide past.