I need to read from a file and be able to split it into columns and ignore a line if it starts with ' . '.

the text file is made of 3 columns but at some lines there are no words in the first column
here is an example of the text file

BANANAS ARE YELLOW
CHEESE IS YELLOW
IS BLUE
IS WHITE
JENNY LIKES PERL

. Line WITH a dot
Also i want to be able to ignore the line that starts with the " . "
thats just a close example of what the file looks like
basically i want to split after reading the file into 3 arrays, the first array having the contents of the first column, the second array having the contents of the second column and so forth. Here is my implementation . i have not used chomp yet

#!/usr/bin/perl

open (nastyfile , "file.txt");
my @lines = <nastyfile>;

foreach $word (@lines)
{
	(@col1,@col2,@col3)= split (/t/,$word);
	print "@col1";
	
}
print @lines;
close (nastyfile);

so basically i want the first array to have the words bananas cheese and jenny

Dani AI

Generated

A few concrete fixes and a compact, robust pattern to follow.

  • The dot check in ’s snippet (/^./) matches any first character; check for a literal dot with /^\./ or /^\s*\./ to allow leading whitespace.
  • chomp (or stripping \r) must run before splitting.
  • If the file is truly tab-delimited, use split /\t/, $line, -1 to preserve empty (missing) fields; splitting on \s+ will collapse runs of whitespace and lose empty columns.
  • Prefer a lexical filehandle and three-arg open, and enable use strict; use warnings;.

The snippet below parses both tab-delimited lines (preserving empty fields) and space-delimited lines where the first column may be missing:

use strict;
use warnings;

my (@col1, @col2, @col3);
open my $fh, '<', 'file.txt' or die "file: $!";

while (my $line = <$fh>) {
    chomp $line;
    $line =~ s/\r$//;               # drop Windows CR if present
    next if $line =~ /^\s*$/;       # skip empty lines
    next if $line =~ /^\s*\./;      # skip lines that start with a dot

    if (index($line, "\t") >= 0) {
        my @f = split /\t/, $line, -1;       # preserve empty fields
        push @col1, $f[0] // '';
        push @col2, $f[1] // '';
        push @col3, $f[2] // '';
        next;
    }

    # space-separated: optional first column, then two required columns
    if ($line =~ /^(?:([^\s]+)\s+)?([^\s]+)\s+([^\s]+)\s*$/) {
        push @col1, $1 // '';
        push @col2, $2;
        push @col3, $3;
    }
    # otherwise the line is malformed for the expected schema; handle as needed
}
close $fh;

Notes and troubleshooting:

  • If fields may contain spaces or quoted values, use Text::CSV (set sep_char => "\t" for tabs).
  • For truly inconsistent files, normalizing the file (ensuring a leading tab for missing first-column rows) is safer than guessing.
  • ’s result mapping is exactly the intended output; this snippet keeps that behavior while fixing the dot-test, preserving empty fields, and using safer IO and parsing practices.

Recommended Answers

All 2 Replies

my (@words1,@words2,@words3);
open file, "/dir/to/file.db";
while (my $line = <file>){
     next if $line =~ /^./;
#this isnt the best way todo this but should work
     my ($word1,$word2,$word3) = split(/ /,$line);
     push @words1, $word1;
     push @words2, $word2;
     push @words3, $word3;
}

try that.....

open(my $INFILE, '<', 'data2.txt');

my (@col1, @col2, @col3);

while (<$INFILE>) {
    next if /^\s*$/ or /^\./;

    chomp;
    my @pieces = split /\s+/;

    push (@col1, shift @pieces) if @pieces == 3;
    push @col2, $pieces[0];
    push @col3, $pieces[1]; 
}


say "@col1";
say "@col2";
say "@col3";

--output:--
BANANAS CHEESE JENNY
ARE IS IS IS LIKES
YELLOW YELLOW BLUE WHITE PERL
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.