formating pipe delimited file

Discussion in 'Perl Misc' started by J, Feb 11, 2004.

  1. J

    J Guest

    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, Feb 11, 2004
    #1
    1. Advertising

  2. J

    J. Gleixner Guest

    J wrote:
    > 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
    >


    split each line, find the maximun length for each column, then use
    printf with the max length of each column.
     
    J. Gleixner, Feb 11, 2004
    #2
    1. Advertising

  3. J

    Bob Walton Guest

    J wrote:

    > 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.

    ....
    > 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
     
    Bob Walton, Feb 11, 2004
    #3
  4. J

    Ben Morrow Guest

    J <> wrote:
    > 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.


    (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.
     
    Ben Morrow, Feb 11, 2004
    #4
  5. J wrote:
    >
    > 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.


    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
     
    John W. Krahn, Feb 12, 2004
    #5
  6. J

    Anno Siegel Guest

    J <> wrote in comp.lang.perl.misc:
    > 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 |


    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
     
    Anno Siegel, Feb 12, 2004
    #6
  7. J

    J Guest

    On Thu, 12 Feb 2004 1:22:28 -0500, John W. Krahn wrote
    (in message <>):

    > J wrote:
    >
    > 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__



    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
     
    J, Feb 13, 2004
    #7
  8. J wrote:
    >
    > On Thu, 12 Feb 2004 1:22:28 -0500, John W. Krahn wrote
    > (in message <>):
    >
    > > J wrote:
    > >
    > > 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__

    >
    > 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
     
    John W. Krahn, Feb 13, 2004
    #8
  9. J

    J Guest

    On Fri, 13 Feb 2004 0:11:50 -0500, John W. Krahn wrote
    (in message <>):

    > J wrote:
    >>
    >> On Thu, 12 Feb 2004 1:22:28 -0500, John W. Krahn wrote
    >> (in message <>):
    >>
    >>> J wrote:
    >>>
    >>> 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__

    >>
    >> 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
    >


    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
     
    J, Feb 16, 2004
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. RyanL
    Replies:
    6
    Views:
    723
    Paul McGuire
    Aug 28, 2007
  2. Elmo Watson

    DataReader to pipe delimited file question

    Elmo Watson, Jan 24, 2008, in forum: ASP .Net
    Replies:
    1
    Views:
    857
    Milosz Skalecki [MCAD]
    Jan 25, 2008
  3. digz
    Replies:
    5
    Views:
    2,214
    Tim Chase
    Mar 19, 2009
  4. Samantha
    Replies:
    7
    Views:
    158
    Samantha
    Mar 7, 2007
  5. Miki Tebeka
    Replies:
    0
    Views:
    174
    Miki Tebeka
    Dec 5, 2012
Loading...

Share This Page