at2marty has asked for the wisdom of the Perl Monks concerning the following question:

I haven't asked a question here in a long time, but my Perl skills are a bit fuzzy. Here is what I am trying to do and have been banging my head against my desk for about a week now. file1 is a list separated by a ":" file2 is a list separated by a "," I want to open both files for reading and output to "file3". The first field of file1 is my "search string" that I'm looking for in file2. if the string doesn't match - print the line from file2 to file3. if the string does match - print the line from file2 to file3 along with the 4th field from file1 to the 6th field of file3. Any help is certainly appreciated.

Replies are listed 'Best First'.
Re: regex and printing
by stevieb (Canon) on Dec 02, 2019 at 20:58 UTC

    Can you please provide a small sample of both files, and some code that you've tried that doesn't seem to be working?

    Each sample should go within <code></code> tags as should the script, so that they are easily identified and copyable for those who can test for you.

Re: regex and printing
by AnomalousMonk (Archbishop) on Dec 02, 2019 at 23:14 UTC

    Text::CSV_XS is enormously useful for reading and writing CSV (Character Separated Value) files. Maybe take a look at it and see if it can at least partially satisfy your needs.


    Give a man a fish:  <%-{-{-{-<

Re: regex and printing
by AnomalousMonk (Archbishop) on Dec 02, 2019 at 23:25 UTC
    The first field of file1 is my "search string" that I'm looking for in file2.

    I don't understand. Is there only one record in file1, and only its first field must be compared against every record in file2? Must the first field of every record in file1 be compared against every record of file2? Etc, etc. (And please be sure to include expected output with the Short, Self-Contained, Correct Example that stevieb suggested.) Please help us to help you.


    Give a man a fish:  <%-{-{-{-<

Re: regex and printing
by NetWallah (Canon) on Dec 03, 2019 at 06:02 UTC
    Best guess at what you want:
    file1.txt needle:filed12:field13:field14:field15:field16 haystack:filed22:field23:field24:field25:field26 lost:filed32:field33:field34:field35:field36 file2.txt Line,one,fff,ggg,hhh line,two,hidden,haystack,in,open Line,three,just,some,junk line,four,has,needle,here more,ending,junk.
    code:
    use strict; use warnings; my @one_lines; open my $one,"<","file1.txt" or die $!; while (<$one>){ chomp; my (@fields)=split /:/; push @one_lines,{KEY=>$fields[0], F4=>$fields[3]}; } close $one; #------ open my $two,"<","file2.txt" or die $!; while (defined(my $line=<$two>)){ chomp $line; my @fields = split /,/,$line; my $matched_line={F4=>""}; for (@one_lines){ next unless $line=~m/$_->{KEY}/; $matched_line=$_; last; } $fields[5] = $matched_line->{F4} if $matched_line->{F4}; print join(",",@fields),"\n"; } close $two;
    Output:
    >perl 11109568.pl Line,one,fff,ggg,hhh line,two,hidden,haystack,in,field24 Line,three,just,some,junk line,four,has,needle,here,field14 more,ending,junk.
    Redirecting output to "file3" is left as an exercise.

                    "From there to here, from here to there, funny things are everywhere." -- Dr. Seuss

Re: regex and printing
by kcott (Archbishop) on Dec 03, 2019 at 10:12 UTC

    G'day at2marty,

    The following is a potential technique you could use. It uses a single pass through both file1 and file2; those files are not open at the same time.

    As others have already pointed out, your question lacks detail. Be aware that I've guessed at the input and have included no checking (e.g. do all records in file1 have at least 4 fields? what to do if they don't? how many fields do records in file2 have? are we appending, replacing, or even extending?). Along with other suggestions, take a look at "How do I post a question effectively?".

    Given file1 looks something like:

    $ cat pm_11109568_file1.txt A:?:?:A4:? B:?:?:B4:? C:?:?:C4:? D:?:?:D4:?

    and file2 looks something like:

    $ cat pm_11109568_file2.txt C,?,?,?,?,W6,? X,?,?,D,?,X6,? Y,?,?,?,?,Y6,B Z,?,?,?,?,Z6,?

    Running this code:

    #!/usr/bin/env perl use strict; use warnings; use autodie; my ($file1, $file2, $file3) = qw{ pm_11109568_file1.txt pm_11109568_file2.txt pm_11109568_file3.txt }; my %search; { open my $fh1, '<', $file1; while (<$fh1>) { my ($field1, $field4) = (split /:/)[0,3]; $search{$field1} = $field4; } } my $re_alt = join '|', keys %search; my $re = qr{(?:^|,)($re_alt)(?:,|$)}; { open my $fh3, '>', $file3; open my $fh2, '<', $file2; while (<$fh2>) { if (/$re/) { my $key = $1; my @fields = split /,/; $fields[5] = $search{$key}; print $fh3 join ',', @fields; } else { print $fh3 $_; } } }

    Produces this output file (i.e. file3):

    $ cat pm_11109568_file3.txt C,?,?,?,?,C4,? X,?,?,D,?,D4,? Y,?,?,?,?,B4,B Z,?,?,?,?,Z6,?

    Just to reinforce what I said at the start, this is just a technique. If it's useful for you, add exception handling, validation, checking, and whatever else you may need (for instance, logging may be appropriate).

    — Ken