?Merging files based on first two comma delimited fields?

Discussion in 'Perl Misc' started by parkerdg@gmail.com, Sep 16, 2005.

  1. Guest

    Thanks to help from this newsgroup I've learned how to put together
    simple Perl scripts. Perl has saved me tons of time in my work and
    I've enjoyed learning to use Perl.

    Now I have a more challenging problem that I'm not experienced enough
    to
    figure out myself. I need to modify a file with data from a second
    file.
    Certain rows in the first file need to be replaced by the corresponding
    rows in the second file. Here are the details:


    File 1, filename.aro
    An input file to a commercial flow network code with the following
    format. The file size is relatively small, maybe 300 lines, ~100 kb:
    [Header]
    Header data

    [Preferences]
    Preference data

    [Junctions]
    4,1,...comma delimited data
    4,504,...comma delimited data
    12,3,...comma delimited data
    3,4,...comma delimited data

    [Pipes]
    1,Pipe,...comma delimited data
    605,Pipe,...comma delimited data
    3,Pipe,...comma delimited data
    10,Pipe,...comma delimited data
    11,Pipe,...comma delimited data

    Certain rows in the [Junctions] and [Pipes] sections need to be
    replaced
    with corresponding lines in file 2. The rows to be replaced will have
    matching data in the first two comma delimited fields. This file will
    be
    very small, typically about 20 lines.


    File 2, filename.csv:
    4,504,...new comma delimited data
    3,4,...new comma delimited data
    605,Pipe,...new comma delimited data
    3,Pipe,...new comma delimited data


    In this example, the 4 lines in file 2 need to overwrite the
    corresponding lines in file 1. I've put together the following script
    but I can't get the comparison of the first two comma delimited
    fields to work. I haven't been able to figure it out and any guidance
    would be appreciated.

    Thanks, Dave

    #!C:\Perl\bin\perl.exe
    # aftmod.pl aftfilename.aro

    # Update AFT Branch and Pipe Data from Comma Delimited Text File (.csv)
    # The directory must contain a comma delimited file with the same
    # filename that defines the modifications: aftfilename.csv

    use warnings;
    use strict;

    # Get AFT model name from command line argument.
    my $filename=$ARGV[0];
    $filename =~ s/\.[^.]*$//; # Strip extension

    #Copy .aro to OLD.aro
    system "copy $filename.aro $filename-OLD.aro\n";

    # Open files for processing
    open (OUT, ">$filename.aro") or die;
    open (CSV , "<$filename.csv") or die;
    open (OLD , "<$filename-OLD.aro") or die;

    # Store CSV file into array
    my @csv_lines = <CSV>;

    # Process OLD .aro file
    foreach my $aro_line (<OLD>) {
    if ($aro_line !~ /,/) {
    print OUT ($aro_line); # Output non-comma delimited rows
    }
    else {
    # Seriously f'd up here
    foreach my $csv_line (@csv_lines) {
    if ($aro_line =~ /^((\w+),(\w+),)/ and $csv_line =~
    m{/$1$}i) {
    print OUT ($csv_line);
    }
    else {
    print OUT ($aro_line);
    last;
    }
    }
    }
    }

    # Close Files
    close OLD;
    close CSV;
    close OUT;
    , Sep 16, 2005
    #1
    1. Advertising

  2. a écrit :
    > Thanks to help from this newsgroup I've learned how to put together
    > simple Perl scripts. Perl has saved me tons of time in my work and
    > I've enjoyed learning to use Perl.
    >
    > Now I have a more challenging problem that I'm not experienced enough
    > to
    > figure out myself. I need to modify a file with data from a second
    > file.
    > Certain rows in the first file need to be replaced by the corresponding
    > rows in the second file. Here are the details:
    >
    >
    > File 1, filename.aro
    > An input file to a commercial flow network code with the following
    > format. The file size is relatively small, maybe 300 lines, ~100 kb:
    > [Header]
    > Header data
    >
    > [Preferences]
    > Preference data
    >
    > [Junctions]
    > 4,1,...comma delimited data
    > 4,504,...comma delimited data
    > 12,3,...comma delimited data
    > 3,4,...comma delimited data
    >
    > [Pipes]
    > 1,Pipe,...comma delimited data
    > 605,Pipe,...comma delimited data
    > 3,Pipe,...comma delimited data
    > 10,Pipe,...comma delimited data
    > 11,Pipe,...comma delimited data
    >
    > Certain rows in the [Junctions] and [Pipes] sections need to be
    > replaced
    > with corresponding lines in file 2. The rows to be replaced will have
    > matching data in the first two comma delimited fields. This file will
    > be
    > very small, typically about 20 lines.
    >
    >
    > File 2, filename.csv:
    > 4,504,...new comma delimited data
    > 3,4,...new comma delimited data
    > 605,Pipe,...new comma delimited data
    > 3,Pipe,...new comma delimited data
    >
    >
    > In this example, the 4 lines in file 2 need to overwrite the
    > corresponding lines in file 1. I've put together the following script
    > but I can't get the comparison of the first two comma delimited
    > fields to work. I haven't been able to figure it out and any guidance
    > would be appreciated.
    >
    > Thanks, Dave
    >
    > #!C:\Perl\bin\perl.exe
    > # aftmod.pl aftfilename.aro
    >
    > # Update AFT Branch and Pipe Data from Comma Delimited Text File (.csv)
    > # The directory must contain a comma delimited file with the same
    > # filename that defines the modifications: aftfilename.csv
    >
    > use warnings;
    > use strict;
    >
    > # Get AFT model name from command line argument.
    > my $filename=$ARGV[0];
    > $filename =~ s/\.[^.]*$//; # Strip extension
    >
    > #Copy .aro to OLD.aro
    > system "copy $filename.aro $filename-OLD.aro\n";
    >
    > # Open files for processing
    > open (OUT, ">$filename.aro") or die;
    > open (CSV , "<$filename.csv") or die;
    > open (OLD , "<$filename-OLD.aro") or die;
    >
    > # Store CSV file into array
    > my @csv_lines = <CSV>;
    >
    > # Process OLD .aro file
    > foreach my $aro_line (<OLD>) {
    > if ($aro_line !~ /,/) {
    > print OUT ($aro_line); # Output non-comma delimited rows
    > }
    > else {
    > # Seriously f'd up here
    > foreach my $csv_line (@csv_lines) {
    > if ($aro_line =~ /^((\w+),(\w+),)/ and $csv_line =~
    > m{/$1$}i) {
    > print OUT ($csv_line);
    > }
    > else {
    > print OUT ($aro_line);
    > last;
    > }
    > }
    > }
    > }
    >
    > # Close Files
    > close OLD;
    > close CSV;
    > close OUT;
    >

    May you put some real datas who came from the two files
    Alexandre Jaquet, Sep 16, 2005
    #2
    1. Advertising

  3. Paul Lalli Guest

    wrote:
    > I need to modify a file with data from a second file.
    > Certain rows in the first file need to be replaced by the corresponding
    > rows in the second file. Here are the details:
    > >

    > File 1, filename.aro
    > An input file to a commercial flow network code with the following
    > format. The file size is relatively small, maybe 300 lines, ~100 kb:
    > [Header]
    > Header data
    >
    > [Preferences]
    > Preference data
    >
    > [Junctions]
    > 4,1,...comma delimited data
    > 4,504,...comma delimited data
    > 12,3,...comma delimited data
    > 3,4,...comma delimited data
    >
    > [Pipes]
    > 1,Pipe,...comma delimited data
    > 605,Pipe,...comma delimited data
    > 3,Pipe,...comma delimited data
    > 10,Pipe,...comma delimited data
    > 11,Pipe,...comma delimited data
    >
    > Certain rows in the [Junctions] and [Pipes] sections need to be
    > replaced
    > with corresponding lines in file 2. The rows to be replaced will have
    > matching data in the first two comma delimited fields. This file will
    > be
    > very small, typically about 20 lines.
    >
    >
    > File 2, filename.csv:
    > 4,504,...new comma delimited data
    > 3,4,...new comma delimited data
    > 605,Pipe,...new comma delimited data
    > 3,Pipe,...new comma delimited data
    >


    Below is a framework to get you started. Assumptions:
    1) The first two fields of the replacement CSV are unique. In other
    words, there is at most one line that starts with exactly
    alpha,123,
    2) There is a blank line at the end of both the [Junctions] and [Pipes]
    sections
    3) You can modify the file to read in your actual replacement csv file,
    rather than using the __DATA__ marker

    For more information about the techniques used here:
    perldoc perlrun (search for the -i option)
    perldoc perlop (search for the .. "flip-flop" operator)

    [untested]
    #!/usr/bin/perl
    use strict;
    use warnings;

    my %replacements;
    while (<DATA>){
    #store a list of replacements, keyed on the first two CSV fields
    my ($key) = /^(.*?,.*?),/;
    $replacements{$key} = $_;
    }

    {
    #enable in-line edit mode
    local @ARGV = ('file_to_modify.txt');
    local $^I = '.bkp';

    while (<>){
    #if we're in a [Junctions] or [Pipes] section
    if ( (/^\[Junctions\]$/ .. /^\s*$/) or
    (/^\[Pipes\]$/ .. /^\s*$/) ) {
    if ( /^(.*?,.*?),/ ) {
    my $key = $1;
    #if the first 2 fields are in our replacements list
    if (exists $replacements{$key}){
    #replace the line with the replacement
    $_ = $replacements{$key};
    }
    }
    }
    } continue {
    print;
    }
    }

    __DATA__
    4,504,...new comma delimited data
    3,4,...new comma delimited data
    605,Pipe,...new comma delimited data
    3,Pipe,...new comma delimited data



    Hope this helps,
    Paul Lalli
    Paul Lalli, Sep 16, 2005
    #3
  4. Stephen O'D Guest

    wrote:
    > Thanks to help from this newsgroup I've learned how to put together
    > simple Perl scripts. Perl has saved me tons of time in my work and
    > I've enjoyed learning to use Perl.
    >
    > Now I have a more challenging problem that I'm not experienced enough
    > to
    > figure out myself. I need to modify a file with data from a second
    > file.
    > Certain rows in the first file need to be replaced by the corresponding
    > rows in the second file. Here are the details:
    >
    >
    > File 1, filename.aro
    > An input file to a commercial flow network code with the following
    > format. The file size is relatively small, maybe 300 lines, ~100 kb:
    > [Header]
    > Header data
    >
    > [Preferences]
    > Preference data
    >
    > [Junctions]
    > 4,1,...comma delimited data
    > 4,504,...comma delimited data
    > 12,3,...comma delimited data
    > 3,4,...comma delimited data
    >
    > [Pipes]
    > 1,Pipe,...comma delimited data
    > 605,Pipe,...comma delimited data
    > 3,Pipe,...comma delimited data
    > 10,Pipe,...comma delimited data
    > 11,Pipe,...comma delimited data
    >
    > Certain rows in the [Junctions] and [Pipes] sections need to be
    > replaced
    > with corresponding lines in file 2. The rows to be replaced will have
    > matching data in the first two comma delimited fields. This file will
    > be
    > very small, typically about 20 lines.
    >
    >
    > File 2, filename.csv:
    > 4,504,...new comma delimited data
    > 3,4,...new comma delimited data
    > 605,Pipe,...new comma delimited data
    > 3,Pipe,...new comma delimited data
    >
    >
    > In this example, the 4 lines in file 2 need to overwrite the
    > corresponding lines in file 1. I've put together the following script
    > but I can't get the comparison of the first two comma delimited
    > fields to work. I haven't been able to figure it out and any guidance
    > would be appreciated.
    >
    > Thanks, Dave
    >
    > #!C:\Perl\bin\perl.exe
    > # aftmod.pl aftfilename.aro
    >
    > # Update AFT Branch and Pipe Data from Comma Delimited Text File (.csv)
    > # The directory must contain a comma delimited file with the same
    > # filename that defines the modifications: aftfilename.csv
    >
    > use warnings;
    > use strict;
    >
    > # Get AFT model name from command line argument.
    > my $filename=$ARGV[0];
    > $filename =~ s/\.[^.]*$//; # Strip extension
    >
    > #Copy .aro to OLD.aro
    > system "copy $filename.aro $filename-OLD.aro\n";
    >
    > # Open files for processing
    > open (OUT, ">$filename.aro") or die;
    > open (CSV , "<$filename.csv") or die;
    > open (OLD , "<$filename-OLD.aro") or die;
    >
    > # Store CSV file into array
    > my @csv_lines = <CSV>;
    >
    > # Process OLD .aro file
    > foreach my $aro_line (<OLD>) {
    > if ($aro_line !~ /,/) {
    > print OUT ($aro_line); # Output non-comma delimited rows
    > }
    > else {
    > # Seriously f'd up here
    > foreach my $csv_line (@csv_lines) {
    > if ($aro_line =~ /^((\w+),(\w+),)/ and $csv_line =~
    > m{/$1$}i) {
    > print OUT ($csv_line);
    > }
    > else {
    > print OUT ($aro_line);
    > last;
    > }
    > }
    > }
    > }
    >
    > # Close Files
    > close OLD;
    > close CSV;
    > close OUT;



    You could read the smaller file into a hash, and then print to you
    output depending on whether it exists or not. An example is better ...

    my $s, $b;
    open ($s, "in2") || die "Could not open small file: $!";
    open ($b, "in1") || die "Could not open big file: $!";

    my %small_file;
    while (<$s>) {
    my ($field1, $field2, $rest) = split /,/,$_,3;
    $small_file{"$field1,$field2"} = $_;
    }

    while (<$b>) {
    my ($field1, $field2, $rest) = split /,/,$_,3;
    if ( exists( $small_file{"$field1,$field2"} ) ) {
    print $small_file{"$field1,$field2"};
    } else {
    print $_;
    }
    }



    $ more in1
    4,1,...comma delimited data
    4,504,...comma delimited data
    12,3,...comma delimited data
    3,4,...comma delimited data
    1,Pipe,...comma delimited data
    605,Pipe,...comma delimited data
    3,Pipe,...comma delimited data
    10,Pipe,...comma delimited data
    11,Pipe,...comma delimited data

    $ more in2
    4,504,...new comma delimited data
    3,4,...new comma delimited data
    605,Pipe,...new comma delimited data
    3,Pipe,...new comma delimited data

    $ perl munge
    4,1,...comma delimited data
    4,504,...new comma delimited data
    12,3,...comma delimited data
    3,4,...new comma delimited data
    1,Pipe,...comma delimited data
    605,Pipe,...new comma delimited data
    3,Pipe,...new comma delimited data
    10,Pipe,...comma delimited data
    11,Pipe,...comma delimited data

    I think that does what you want ...
    Stephen O'D, Sep 16, 2005
    #4
  5. wrote:
    > Thanks to help from this newsgroup I've learned how to put together
    > simple Perl scripts. Perl has saved me tons of time in my work and
    > I've enjoyed learning to use Perl.
    >
    > Now I have a more challenging problem that I'm not experienced enough
    > to
    > figure out myself. I need to modify a file with data from a second
    > file.
    > Certain rows in the first file need to be replaced by the corresponding
    > rows in the second file. Here are the details:
    >
    >
    > File 1, filename.aro
    > An input file to a commercial flow network code with the following
    > format. The file size is relatively small, maybe 300 lines, ~100 kb:
    > [Header]
    > Header data
    >
    > [Preferences]
    > Preference data
    >
    > [Junctions]
    > 4,1,...comma delimited data
    > 4,504,...comma delimited data
    > 12,3,...comma delimited data
    > 3,4,...comma delimited data
    >
    > [Pipes]
    > 1,Pipe,...comma delimited data
    > 605,Pipe,...comma delimited data
    > 3,Pipe,...comma delimited data
    > 10,Pipe,...comma delimited data
    > 11,Pipe,...comma delimited data
    >
    > Certain rows in the [Junctions] and [Pipes] sections need to be
    > replaced
    > with corresponding lines in file 2. The rows to be replaced will have
    > matching data in the first two comma delimited fields. This file will
    > be
    > very small, typically about 20 lines.
    >
    >
    > File 2, filename.csv:
    > 4,504,...new comma delimited data
    > 3,4,...new comma delimited data
    > 605,Pipe,...new comma delimited data
    > 3,Pipe,...new comma delimited data
    >
    >
    > In this example, the 4 lines in file 2 need to overwrite the
    > corresponding lines in file 1. I've put together the following script
    > but I can't get the comparison of the first two comma delimited
    > fields to work. I haven't been able to figure it out and any guidance
    > would be appreciated.
    >


    I'd try to make life easier for myself and make use of CPAN. Use
    something like Config::IniFiles for reading and writing the complete
    file (this assumes I haven't misunderstood the file format), and then
    something like DBD::CSV or Text::CSV_XS to handle the comma-separated
    rows. Comparison of the fields should then be relatively straightforward.

    Mark
    Mark Clements, Sep 16, 2005
    #5
  6. wrote:
    > I need to modify a file with data from a second
    > file.
    > Certain rows in the first file need to be replaced by the corresponding
    > rows in the second file. Here are the details:
    >
    >
    > File 1, filename.aro
    > An input file to a commercial flow network code with the following
    > format. The file size is relatively small, maybe 300 lines, ~100 kb:
    > [Header]
    > Header data
    >
    > [Preferences]
    > Preference data
    >
    > [Junctions]
    > 4,1,...comma delimited data
    > 4,504,...comma delimited data
    > 12,3,...comma delimited data
    > 3,4,...comma delimited data
    >
    > [Pipes]
    > 1,Pipe,...comma delimited data
    > 605,Pipe,...comma delimited data
    > 3,Pipe,...comma delimited data
    > 10,Pipe,...comma delimited data
    > 11,Pipe,...comma delimited data
    >
    > Certain rows in the [Junctions] and [Pipes] sections need to be
    > replaced
    > with corresponding lines in file 2. The rows to be replaced will have
    > matching data in the first two comma delimited fields. This file will
    > be
    > very small, typically about 20 lines.
    >
    >
    > File 2, filename.csv:
    > 4,504,...new comma delimited data
    > 3,4,...new comma delimited data
    > 605,Pipe,...new comma delimited data
    > 3,Pipe,...new comma delimited data
    >
    >
    > In this example, the 4 lines in file 2 need to overwrite the
    > corresponding lines in file 1. I've put together the following script
    > but I can't get the comparison of the first two comma delimited
    > fields to work. I haven't been able to figure it out and any guidance
    > would be appreciated.


    This is an easy problem for Awk programmers:

    BEGIN { FS = ","
    ## We want to read 2nd file first.
    t = ARGV[1] ; ARGV[1]=ARGV[2] ; ARGV[2]=t
    }
    ## Reading file with updates?
    FILENAME == ARGV[1] { a[$1,$2]=$0 ; next }
    ## Now we're reading the main file.
    ($1,$2) in a { $0 = a[$1,$2] }
    { print }
    William James, Sep 16, 2005
    #6
  7. Guest

    wrote:
    > Thanks to help from this newsgroup I've learned how to put together
    > simple Perl scripts. Perl has saved me tons of time in my work and
    > I've enjoyed learning to use Perl.
    >
    > Now I have a more challenging problem that I'm not experienced enough
    > to
    > figure out myself. I need to modify a file with data from a second
    > file.
    > Certain rows in the first file need to be replaced by the corresponding
    > rows in the second file. Here are the details:
    >

    ....

    Assuming no other complications (like the fields being optionally quoted
    or otherwise escaped):

    > # Open files for processing
    > open (OUT, ">$filename.aro") or die;
    > open (CSV , "<$filename.csv") or die;
    > open (OLD , "<$filename-OLD.aro") or die;
    >
    > # Store CSV file into array
    > my @csv_lines = <CSV>;


    # use the hash, Luke, use the hash.

    my %csv_line;
    while (<CSV>) {
    my ($key1,$key2) = split /,/;
    $csv_line{"$key1,$key2"}=$_;
    };


    > # Process OLD .aro file
    > foreach my $aro_line (<OLD>) {
    > if ($aro_line !~ /,/) {
    > print OUT ($aro_line); # Output non-comma delimited rows
    > }
    > else {

    my ($key1,$key2) = split /,/;
    print OUT $csv_line{"$key1,$key2"} || $_;
    > }
    > }
    >
    > # Close Files
    > close OLD;
    > close CSV;
    > close OUT;


    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , Sep 16, 2005
    #7
  8. wrote:
    > Thanks to help from this newsgroup I've learned how to put together
    > simple Perl scripts. Perl has saved me tons of time in my work and
    > I've enjoyed learning to use Perl.
    >
    > Now I have a more challenging problem that I'm not experienced enough
    > to
    > figure out myself. I need to modify a file with data from a second
    > file.
    > Certain rows in the first file need to be replaced by the corresponding
    > rows in the second file. Here are the details:
    >
    >
    > File 1, filename.aro
    > An input file to a commercial flow network code with the following
    > format. The file size is relatively small, maybe 300 lines, ~100 kb:
    > [Header]
    > Header data
    >
    > [Preferences]
    > Preference data
    >
    > [Junctions]
    > 4,1,...comma delimited data
    > 4,504,...comma delimited data
    > 12,3,...comma delimited data
    > 3,4,...comma delimited data
    >
    > [Pipes]
    > 1,Pipe,...comma delimited data
    > 605,Pipe,...comma delimited data
    > 3,Pipe,...comma delimited data
    > 10,Pipe,...comma delimited data
    > 11,Pipe,...comma delimited data
    >
    > Certain rows in the [Junctions] and [Pipes] sections need to be
    > replaced
    > with corresponding lines in file 2. The rows to be replaced will have
    > matching data in the first two comma delimited fields. This file will
    > be
    > very small, typically about 20 lines.
    >
    >
    > File 2, filename.csv:
    > 4,504,...new comma delimited data
    > 3,4,...new comma delimited data
    > 605,Pipe,...new comma delimited data
    > 3,Pipe,...new comma delimited data
    >
    >
    > In this example, the 4 lines in file 2 need to overwrite the
    > corresponding lines in file 1. I've put together the following script
    > but I can't get the comparison of the first two comma delimited
    > fields to work. I haven't been able to figure it out and any guidance
    > would be appreciated.
    >
    > Thanks, Dave
    >
    > #!C:\Perl\bin\perl.exe
    > # aftmod.pl aftfilename.aro
    >
    > # Update AFT Branch and Pipe Data from Comma Delimited Text File (.csv)
    > # The directory must contain a comma delimited file with the same
    > # filename that defines the modifications: aftfilename.csv
    >
    > use warnings;
    > use strict;
    >
    > # Get AFT model name from command line argument.
    > my $filename=$ARGV[0];
    > $filename =~ s/\.[^.]*$//; # Strip extension
    >
    > #Copy .aro to OLD.aro
    > system "copy $filename.aro $filename-OLD.aro\n";
    >
    > # Open files for processing
    > open (OUT, ">$filename.aro") or die;
    > open (CSV , "<$filename.csv") or die;
    > open (OLD , "<$filename-OLD.aro") or die;
    >
    > # Store CSV file into array
    > my @csv_lines = <CSV>;
    >
    > # Process OLD .aro file
    > foreach my $aro_line (<OLD>) {
    > if ($aro_line !~ /,/) {
    > print OUT ($aro_line); # Output non-comma delimited rows
    > }
    > else {
    > # Seriously f'd up here
    > foreach my $csv_line (@csv_lines) {
    > if ($aro_line =~ /^((\w+),(\w+),)/ and $csv_line =~
    > m{/$1$}i) {
    > print OUT ($csv_line);
    > }
    > else {
    > print OUT ($aro_line);
    > last;
    > }
    > }
    > }
    > }
    >
    > # Close Files
    > close OLD;
    > close CSV;
    > close OUT;


    Here is one way to do it (UNTESTED):


    #!C:\Perl\bin\perl.exe
    # aftmod.pl aftfilename.aro

    # Update AFT Branch and Pipe Data from Comma Delimited Text File (.csv)
    # The directory must contain a comma delimited file with the same
    # filename that defines the modifications: aftfilename.csv

    use warnings;
    use strict;

    # Get AFT model name from command line argument.
    ( my $filename = $ARGV[ 0 ] ) =~ s/\.[^.]*\z//; # Strip extension

    # rename .aro to OLD.aro
    rename "$filename.aro", "$filename-OLD.aro"
    or die "Cannot rename $filename.aro to $filename-OLD.aro: $!";

    # Open files for processing
    open CSV, '<', "$filename.csv" or die "Cannot open $filename.csv: $!";
    open OLD, '<', "$filename-OLD.aro" or die "Cannot open $filename-OLD.aro: $!";
    open OUT, '>', "$filename.aro" or die "Cannot open $filename.aro: $!";


    my %csv;
    while ( <CSV> ) {
    my $key = join ',', ( split /,/ )[ 0, 1 ];
    $csv{ $key } = $_;
    }
    close CSV;


    while ( <OLD> ) {
    my $key = join ',', ( split /,/ )[ 0, 1 ];
    $_ = $csv{ $key } if exists $csv{ $key };
    print OUT;
    }
    close OUT;
    close OLD;

    __END__



    John
    --
    use Perl;
    program
    fulfillment
    John W. Krahn, Sep 16, 2005
    #8
  9. Guest

    Awesome - the hash suggestion works perfectly!

    Dave Parker

    John W. Krahn wrote:
    > wrote:
    > > Thanks to help from this newsgroup I've learned how to put together
    > > simple Perl scripts. Perl has saved me tons of time in my work and
    > > I've enjoyed learning to use Perl.
    > >
    > > Now I have a more challenging problem that I'm not experienced enough
    > > to
    > > figure out myself. I need to modify a file with data from a second
    > > file.
    > > Certain rows in the first file need to be replaced by the corresponding
    > > rows in the second file. Here are the details:
    > >
    > >
    > > File 1, filename.aro
    > > An input file to a commercial flow network code with the following
    > > format. The file size is relatively small, maybe 300 lines, ~100 kb:
    > > [Header]
    > > Header data
    > >
    > > [Preferences]
    > > Preference data
    > >
    > > [Junctions]
    > > 4,1,...comma delimited data
    > > 4,504,...comma delimited data
    > > 12,3,...comma delimited data
    > > 3,4,...comma delimited data
    > >
    > > [Pipes]
    > > 1,Pipe,...comma delimited data
    > > 605,Pipe,...comma delimited data
    > > 3,Pipe,...comma delimited data
    > > 10,Pipe,...comma delimited data
    > > 11,Pipe,...comma delimited data
    > >
    > > Certain rows in the [Junctions] and [Pipes] sections need to be
    > > replaced
    > > with corresponding lines in file 2. The rows to be replaced will have
    > > matching data in the first two comma delimited fields. This file will
    > > be
    > > very small, typically about 20 lines.
    > >
    > >
    > > File 2, filename.csv:
    > > 4,504,...new comma delimited data
    > > 3,4,...new comma delimited data
    > > 605,Pipe,...new comma delimited data
    > > 3,Pipe,...new comma delimited data
    > >
    > >
    > > In this example, the 4 lines in file 2 need to overwrite the
    > > corresponding lines in file 1. I've put together the following script
    > > but I can't get the comparison of the first two comma delimited
    > > fields to work. I haven't been able to figure it out and any guidance
    > > would be appreciated.
    > >
    > > Thanks, Dave
    > >
    > > #!C:\Perl\bin\perl.exe
    > > # aftmod.pl aftfilename.aro
    > >
    > > # Update AFT Branch and Pipe Data from Comma Delimited Text File (.csv)
    > > # The directory must contain a comma delimited file with the same
    > > # filename that defines the modifications: aftfilename.csv
    > >
    > > use warnings;
    > > use strict;
    > >
    > > # Get AFT model name from command line argument.
    > > my $filename=$ARGV[0];
    > > $filename =~ s/\.[^.]*$//; # Strip extension
    > >
    > > #Copy .aro to OLD.aro
    > > system "copy $filename.aro $filename-OLD.aro\n";
    > >
    > > # Open files for processing
    > > open (OUT, ">$filename.aro") or die;
    > > open (CSV , "<$filename.csv") or die;
    > > open (OLD , "<$filename-OLD.aro") or die;
    > >
    > > # Store CSV file into array
    > > my @csv_lines = <CSV>;
    > >
    > > # Process OLD .aro file
    > > foreach my $aro_line (<OLD>) {
    > > if ($aro_line !~ /,/) {
    > > print OUT ($aro_line); # Output non-comma delimited rows
    > > }
    > > else {
    > > # Seriously f'd up here
    > > foreach my $csv_line (@csv_lines) {
    > > if ($aro_line =~ /^((\w+),(\w+),)/ and $csv_line =~
    > > m{/$1$}i) {
    > > print OUT ($csv_line);
    > > }
    > > else {
    > > print OUT ($aro_line);
    > > last;
    > > }
    > > }
    > > }
    > > }
    > >
    > > # Close Files
    > > close OLD;
    > > close CSV;
    > > close OUT;

    >
    > Here is one way to do it (UNTESTED):
    >
    >
    > #!C:\Perl\bin\perl.exe
    > # aftmod.pl aftfilename.aro
    >
    > # Update AFT Branch and Pipe Data from Comma Delimited Text File (.csv)
    > # The directory must contain a comma delimited file with the same
    > # filename that defines the modifications: aftfilename.csv
    >
    > use warnings;
    > use strict;
    >
    > # Get AFT model name from command line argument.
    > ( my $filename = $ARGV[ 0 ] ) =~ s/\.[^.]*\z//; # Strip extension
    >
    > # rename .aro to OLD.aro
    > rename "$filename.aro", "$filename-OLD.aro"
    > or die "Cannot rename $filename.aro to $filename-OLD.aro: $!";
    >
    > # Open files for processing
    > open CSV, '<', "$filename.csv" or die "Cannot open $filename.csv: $!";
    > open OLD, '<', "$filename-OLD.aro" or die "Cannot open $filename-OLD.aro: $!";
    > open OUT, '>', "$filename.aro" or die "Cannot open $filename.aro: $!";
    >
    >
    > my %csv;
    > while ( <CSV> ) {
    > my $key = join ',', ( split /,/ )[ 0, 1 ];
    > $csv{ $key } = $_;
    > }
    > close CSV;
    >
    >
    > while ( <OLD> ) {
    > my $key = join ',', ( split /,/ )[ 0, 1 ];
    > $_ = $csv{ $key } if exists $csv{ $key };
    > print OUT;
    > }
    > close OUT;
    > close OLD;
    >
    > __END__
    >
    >
    >
    > John
    > --
    > use Perl;
    > program
    > fulfillment
    , Sep 17, 2005
    #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. Yama

    Comma Delimited

    Yama, Dec 15, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    383
    Ken Cox [Microsoft MVP]
    Dec 16, 2003
  2. John B. Lorenz

    Reading Comma Delimited Files

    John B. Lorenz, Jul 7, 2003, in forum: C Programming
    Replies:
    1
    Views:
    3,615
    Joe Wright
    Jul 8, 2003
  3. RyanL
    Replies:
    6
    Views:
    667
    Paul McGuire
    Aug 28, 2007
  4. triangle
    Replies:
    1
    Views:
    106
    Gunnar Hjalmarsson
    Jan 30, 2004
  5. AMT2K5
    Replies:
    1
    Views:
    179
    Eric Schwartz
    Nov 8, 2005
Loading...

Share This Page