Discussion:
formating pipe delimited file
(too old to reply)
J
2004-02-11 23:03:40 UTC
Permalink
I have a file with 40000 lines. Each line is a row of data, and the fields
are seperated by pipes ( | ). I would like to align all pipes so that the
fields will line up.

example:

field1 | 100 | 1 | | |
field2islong| | example | | 3 |

would become

field1 | 100 | 1 | | |
field2islong| | example | | 3 |


anyone have any ideas.

J
J. Gleixner
2004-02-11 23:16:36 UTC
Permalink
Post by J
I have a file with 40000 lines. Each line is a row of data, and the fields
are seperated by pipes ( | ). I would like to align all pipes so that the
fields will line up.
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
would become
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
anyone have any ideas.
J
split each line, find the maximun length for each column, then use
printf with the max length of each column.
Bob Walton
2004-02-11 23:24:12 UTC
Permalink
Post by J
I have a file with 40000 lines. Each line is a row of data, and the fields
are seperated by pipes ( | ). I would like to align all pipes so that the
fields will line up.
...
Post by J
J
Do you know any information on field lengths up front? If not, you'll
have to pass through your data once to determine the maximum length of
each field, then pass through it again to output it. The actual program
to do that is trivial. The "x" operator would be useful in it.

You will have to decide if you want to read the entire file to memory
the first time through (I don't know what 40000 lines translates to in
bytes, or what that number of bytes means to your computer system), or
whether the file should be read twice.
--
Bob Walton
Email: http://bwalton.com/cgi-bin/emailbob.pl
Ben Morrow
2004-02-11 23:28:09 UTC
Permalink
Post by J
I have a file with 40000 lines. Each line is a row of data, and the fields
are seperated by pipes ( | ). I would like to align all pipes so that the
fields will line up.
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
would become
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
anyone have any ideas.
(untested)

use Fcntl qw/:seek/;

{
open my $FILE, '<', $file or die "can't open $file: $!";
my @lengths;

while (<$FILE>) {
my @f = split /\|/;
for (0..$#f) {
$lengths[$_] < length $f[$_]
and $lengths[$_] = length $f[$_];
}
}

my $fmt = join '|', map "%-$_s", @lengths;

seek $FILE, 0, SEEK_SET;

{
open my $OUT, '>', "$file.new"
or die "can't create $file.new: $!";

local $\ = "\n";
# or maybe "|\n", if the last field is really null

while (<$FILE>) {
print $OUT sprintf $fmt => split /\|/;
}
}
}

rename "$file.new", $file or die "can't overwrite $file: $!";
--
Although few may originate a policy, we are all able to judge it.
- Pericles of Athens, c.430 B.C.
***@morrow.me.uk
John W. Krahn
2004-02-12 06:22:28 UTC
Permalink
Post by J
I have a file with 40000 lines. Each line is a row of data, and the fields
are seperated by pipes ( | ). I would like to align all pipes so that the
fields will line up.
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
would become
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
anyone have any ideas.
Something like this should work:

#!/usr/bin/perl
use warnings;
use strict;

( $^I, @ARGV ) = ( '.bak', 'yourfile.txt' );

my @lens = map length, split /\|/, <>, -1;
while ( <> ) {
chomp;
my $i = -1;
$lens[ ++$i ] < $_ and $lens[ $i ] = $_ for map length, split /\|/, $_, -1;
}
@ARGV = $ARGV;
while ( <> ) {
chomp;
my $i;
print join( '|', map sprintf( '%-*s', $lens[ $i++ ], $_ ), split /\|/, $_, -1 ), "\n";
}

__END__



John
--
use Perl;
program
fulfillment
J
2004-02-13 03:17:40 UTC
Permalink
Post by John W. Krahn
#!/usr/bin/perl
use warnings;
use strict;
while ( <> ) {
chomp;
my $i = -1;
$lens[ ++$i ] < $_ and $lens[ $i ] = $_ for map length, split /\|/, $_, -1;
}
@ARGV = $ARGV;
while ( <> ) {
chomp;
my $i;
print join( '|', map sprintf( '%-*s', $lens[ $i++ ], $_ ), split /\|/, $_, -1 ), "\n";
}
__END__
I'm having a hard time understand this line of code
$lens[ ++$i ] < $_ and $lens[ $i ] = $_ for map length, split /\|/, $_,-1

Could some one explain this line of code.

John
John W. Krahn
2004-02-13 05:11:50 UTC
Permalink
Post by J
Post by John W. Krahn
#!/usr/bin/perl
use warnings;
use strict;
while ( <> ) {
chomp;
my $i = -1;
$lens[ ++$i ] < $_ and $lens[ $i ] = $_ for map length, split /\|/, $_, -1;
}
@ARGV = $ARGV;
while ( <> ) {
chomp;
my $i;
print join( '|', map sprintf( '%-*s', $lens[ $i++ ], $_ ), split /\|/,
$_, -1 ), "\n";
}
__END__
I'm having a hard time understand this line of code
$lens[ ++$i ] < $_ and $lens[ $i ] = $_ for map length, split /\|/, $_,-1
Could some one explain this line of code.
Sure, to put it more verbosely:

# set $index to -1 because we pre-increment it in the loop
my $index = -1;

# split the line in $_ using the pipe '|' character
# third argument is -1 to get trailing empty fields
for my $field ( split /\|/, $_, -1 ) {

my $length = length $field;

++$index;

if ( $lens[ $index ] < $length ) {

# store $length in the array @lens if it is
# greater than the previous value in @lens
$lens[ $index ] = $length;
}
}



John
--
use Perl;
program
fulfillment
J
2004-02-16 04:03:49 UTC
Permalink
Post by John W. Krahn
Post by J
Post by John W. Krahn
#!/usr/bin/perl
use warnings;
use strict;
while ( <> ) {
chomp;
my $i = -1;
$lens[ ++$i ] < $_ and $lens[ $i ] = $_ for map length, split /\|/, $_, -1;
}
@ARGV = $ARGV;
while ( <> ) {
chomp;
my $i;
print join( '|', map sprintf( '%-*s', $lens[ $i++ ], $_ ), split /\|/, $_, -1 ), "\n";
}
__END__
I'm having a hard time understand this line of code
$lens[ ++$i ] < $_ and $lens[ $i ] = $_ for map length, split /\|/, $_,-1
Could some one explain this line of code.
# set $index to -1 because we pre-increment it in the loop
my $index = -1;
# split the line in $_ using the pipe '|' character
# third argument is -1 to get trailing empty fields
for my $field ( split /\|/, $_, -1 ) {
my $length = length $field;
++$index;
if ( $lens[ $index ] < $length ) {
$lens[ $index ] = $length;
}
}
John
I understand a little bit better. That is the hardest thing about perl for
me, is understanding all the shortcut codes.

Thanks for explaining stuff to me.

J

Anno Siegel
2004-02-12 09:57:30 UTC
Permalink
Post by J
I have a file with 40000 lines. Each line is a row of data, and the fields
are seperated by pipes ( | ). I would like to align all pipes so that the
fields will line up.
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
would become
field1 | 100 | 1 | | |
field2islong| | example | | 3 |
Ah... an alignment problem. That's an occasion to plug Text::Table :)

use Text::Table;

# Define a table with 5 columns, untitled, with "|" as column separators
my $tb = Text::Table->new( ('', \ '|') x 5);

# Fill in the data lines
$tb->add( split /\|/) while <DATA>;

# print the re-formatted lines
print $tb;

__DATA__
field1 | 100 | 1 | | |
field2islong| | example | | 3 |


Anno
Loading...