To add to the answer, I will write a clear and simple one. This version:
- uses only the most basic Perl functions and constructs, so anyone who knows even a little Perl should get it quite quickly. Not to offend or anything, and there's no shame in being a newbie - I'm just trying to write something that you'll be able to understand no matter what your skill level is.
- accepts either tabs or spaces as a delimiter, allowing them to be mixed freely. Commented-out code will detail a trivial way to enforce an either-or throughout the entire document.
- prints nice error messages when it encoutnters bad values. Should show the illegal value and the line it appeared on.
- allows you to process the data however you like. I'm not going to store it in an array or anything, just put a
...
at one point, and there you will add in a bit of code to do whatever processing of the data on a given line you want to perform.
So here goes:
use strict;
use warnings;
open(my $data, "<", $filename);
# define $filename before this, or get it from the user
my $whitespace = "\t ";
chomp(my @data = <$data>);
# check first line for whitespace to enforce...
#if($data[0] =~ /\t/ and $data[0] !~ / /) {
# $whitespace = "\t";
#} elsif($data[0] =~ / / and $data[0] !~ /\t/) {
# $whitespace = " ";
#} else {
# warn "Warning: mixed whitespace on line 1 - ignoring whitespace.\n";
#}
foreach my $n (0 .. $#data) {
my @fields = split(/[$whitespace]+/, $data[$n]);
foreach my $f (@fields) {
if($f !~ /-?\d/) { # \D will call "-12" invalid
if($f =~ /\s/) {
warn "Warning: invalid whitespace use at line $n - ignoring.\n";
} else {
warn "Warning: invalid value '$f' at line $n - ignoring.\n";
}
} else {
... # do something with $f, or...
}
}
... # do something with @fields if you want to process the whole list
}
There are better, faster, more compact, and perhaps even more readable (depending on who you ask) ways to do it, but this one uses the most basic constructs, and any Perl programmer should be able to read this, regardless of skill level (okay, if you're just starting with Perl as a first language, you may not know any of it, but then you shouldn't be trying to do something like this quite yet).
EDIT: fixed my regex for matching integers. It was lazy before, and allowed "12-4", which is obviously not an integer (though it evaluates to one - but that's much more complicated (well, not really, but it's not what the OP wants (or is it? It would be a fun feature (INSERT LISP JOKE HERE)))). Thanks wisnij - I'm glad I re-read your post, since you wrote a better regex than I did.