Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

jonasbn (1153)

jonasbn
  reversethis-{gro.napc} {ta} {nbsanoj}
http://e-diot.dk/
AOL IM: BJonasN (Add Buddy, Send Message)

Perl Programmer located in Copenhagen, Denmark. Active member of Copenhagen Perl Mongers.

Author of:

  • Business::DK::CPR
  • Business::DK::CVR
  • Business::DK::PO
  • Business::OnlinePayment::CashCow
  • Date::Holidays
  • Date::Holidays::Abstract
  • Date::Holidays::Super
  • Date::Pregnancy
  • Games::Bingo
  • Games::Bingo::Bot
  • Games::Bingo::Print
  • Module::Info::File
  • Module::Template::Setup
  • Test::Timer

and maintainer of:

  • Tie::Tools
  • XML::Conf
  • Workflow

Journal of jonasbn (1153)

Saturday February 10, 2007
10:42 AM

No Solution without a Problem

[ #32365 ]

Our local LUG, (SSLUG) have a general programming list. A part from other languages, a Perl question gets posted once in a while.

Today some guy asked a question about reading two different things via STDIN, like this:

./test.pl < fil1

After reading the file the program should ask questions to the user, recording the responses from STDIN.

The example outline was pretty simple:

#! /usr/bin/perl
 
use strict;
use warnings;
 
my @lines;
my $line;
while ($line = <STDIN>) {
    push @lines,$line;
}
#STDIN->clearerr;
#seek(STDIN, 0, 1);
 
my $input;
foreach $line (@lines) {
    print "$line";
    $input = <STDIN>;
    print "You said $input\n";
}

But the author of the question had problems getting the responses from STDIN.

I had no idea how to solve this, probably because I would never implement a program this way - but I found the problem quite interesting. So I read a few man pages, tried out a few things, but without luck - I was simply not familiar with that part of the Perl language.

I primarily do web and database stuff, I hardly ever work on files and if I do it is very basic operations and I love using Tie::Array.

Before I found a solution, the author posted the solution himself.

I refactored his original to give a more suitable example:

A small program, which reads a number of questions from a file via STDIN, prompts the user for a response via STDIN and prints question and response in conjunction to STDERR.

#! /usr/bin/perl -w
 
use strict;
 
my @questions;
while (my $question = <STDIN>) {
    push @questions,$question;
}
close(STDIN);
 
open(STDIN,'/dev/tty');
foreach (@questions) {
    print "$_";
    print STDERR "$_";
    print STDERR <STDIN>."\n";
}
 
exit(0);
 
__END__
 
Usage: questions.pl <questions.txt 2>data.txt

What bothers me is the fact that I did not know how to do this is Perl, but as written earlier, I would never come across a problem like this and therefor not the solution.

I wish there would be an open variant of the Perl Cookbook, like a wiki, where these recipes/solutions providing basic solutions to basic problems using either CPAN modules or preferably basic Perl could be shared.

In order to improve as a programmer I guess is you have to be exposed to a variation of problems, but also a variation of tools, here meaning programming languages. I remember when going back from VB.NET and PL/SQL to Perl I saw Perl in a new light.

I also remember when I started out with 'Learning Perl', I loved solving the tasks, since this gave me exposure to Perl parts, without having being related to work or something else with a deadline, some legacy code or cultural dependency controlling the way you would or could solve the problem. Of course there is also a cultural influence imposed by the author and possibly the author of Perl and I could go on.

It is nice to sometimes to be able look at problem with a white sheet of paper and be able to start from scratch. Break the problem down, prototype, experiment, understand and finally implement and solve the problem.

The paradigme I attempt to enforce it an approach of divide and conquer, but unless exposed to diverse problems the solutions will most often be based on the same, sometimes bad solutions and not necessarily the best practice...

I guess the bare bone nature outlined by the poster to the LUG list made me interested there was a working snippet to a simple problem, but not a solution.

Well anyway I might have to consider how to get exposed to a larger variety of problems one way or the other, so I can learn a wider variety of solutions and a wider use of Perl and other tools.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • #!/usr/bin/perl -w
    use strict;

    die "Usage: $0 questions.txt [morequestions.txt ...] > answers.txt"
        if not @ARGV;

    while( <> ) {
        print STDERR $_;
        print $_;
        print scalar <STDIN>;
    }

    The key is that the question files must be given as commandline arguments, not passed in via redirection. The <> diamond operator will read from the files listed in @ARGV and you can read STDIN separately from it at the same time.

    • Ah, much more in line with what I would probably do, however not as short and artistic.

      Thanks for the solution it is very nice.
    • Yea, this is a suitable solution for

      foo.pl inputfile.txt

      But what if you want to do

      grep bar inputfile.txt | foo.pl

      instead?

      --
      Ordinary morality is for ordinary people. -- Aleister Crowley
      • If you use bash, you can use process substitution instead:

        foo.pl <( grep bar inputfile.txt )

        • Far too complicated :)
          --
          Ordinary morality is for ordinary people. -- Aleister Crowley
          • It’s more reliable (/dev/tty isn’t always available) and more flexible (you don’t need Expect to feed it answers from a file, you just redirect standard input). But the clincher for me is that it’s still less and simpler code. Cf. Carter’s Compass.

            • Well, that's a borderline. IMO the API should always be nicer than the guts :)
              --
              Ordinary morality is for ordinary people. -- Aleister Crowley