質問

I'm new in Perl, so it's maybe a very basic case that i still can't understand.

Case:
Program tell user to types the file name.
User types the file name (1 or more files).
Program read the content of file input.
If it's single file input, then it just prints the entire content of it.
if it's multi files input, then it combines the contents of each file in a sequence.
And then print result to a temporary new file, which located in the same directory with the program.pl .

file1.txt:
head
a
b
end

file2.txt:
head
c
d
e
f
end

SINGLE INPUT program ioSingle.pl:

#!/usr/bin/perl 

print "File name: ";
$userinput =  <STDIN>; chomp ($userinput);

#read content from input file
open ("FILEINPUT", $userinput) or die ("can't open file");


#PRINT CONTENT selama ada di file tsb
while (<FILEINPUT>) { 
print ;  }

close FILEINPUT;

SINGLE RESULT in cmd:

>perl ioSingle.pl
File name: file1.txt
head
a
b
end

I found tutorial code that combine content from multifiles input but cannot adapt the while argument to code above:

while ($userinput = <>) {
      print ($userinput);
 }

I was stucked at making it work for multifiles input,
How am i suppose to reformat the code so my program could give result like this?

EXPECTED MULTIFILES RESULT in cmd:

>perl ioMulti.pl
File name: file1.txt file2.txt head
a
b
end
head
c
d
e
f
end

i appreciate your response :)

役に立ちましたか?

解決

A good way to start working on a problem like this, is to break it down into smaller sections.

Your problem seems to break down to this:

  • get a list of filenames
  • for each file in the list
    • display the file contents

So think about writing subroutines that do each of these tasks. You already have something like a subroutine to display the contents of the file.

sub display_file_contents {
  # filename is the first (and only argument) to the sub
  my $filename = shift;

  # Use lexical filehandl and three-arg open
  open my $filehandle, '<', $filename or die $!;

  # Shorter version of your code
  print while <$filehandle>;
}

The next task is to get our list of files. You already have some of that too.

sub get_list_of_files {
  print 'File name(s): ';
  my $files = <STDIN>;
  chomp $files;

  # We might have more than one filename. Need to split input.
  # Assume filenames are separated by whitespace
  # (Might need to revisit that assumption - filenames can contain spaces!)
  my @filenames = split /\s+/, $files;

  return @filenames;
}

We can then put all of that together in the main program.

#!/usr/bin/perl

use strict;
use warnings;

my @list_of_files = get_list_of_files();
foreach my $file (@list_of_files) {
  display_file_contents($file);
}

By breaking the task down into smaller tasks, each one becomes easier to deal with. And you don't need to carry the complexity of the whole program in you head at one time.

p.s. But like JRFerguson says, taking the list of files as command line parameters would make this far simpler.

他のヒント

The easy way is to use the diamond operator <> to open and read the files specified on the command line. This would achieve your objective:

while (<>) {
    chomp;
    print "$_\n";
}

Thus: ioSingle.pl file1.txt file2.txt

If this is the sole objective, you can reduce this to a command line script using the -p or -n switch like:

perl -pe '1' file1.txt file2.txt

perl -ne 'print' file1.txt file2.txt

These switches create implicit loops around the -e commands. The -p switch prints $_ after every loop as if you had written:

LINE:
while (<>) {
    # your code...
} continue {
    print;
}

Using -n creates:

LINE:
while (<>) {
# your code...
}

Thus, -p adds an implicit print statement.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top