perl text file processing using hash


 
Thread Tools Search this Thread
Top Forums UNIX for Advanced & Expert Users perl text file processing using hash
# 1  
Old 01-31-2011
Question perl text file processing using hash

Hi Experts,

I have this requirement to process large files (200MB+).Format of files is like:
Code:
recordstart
val1               1
val2               2
val3               4
recordstart
val1               5
val2               6
val3               1
val4               1
recordstart
val1               1 
val2               3
val3               6

Final output required is
Code:
val1,val2,val3
1,2,4
5,6,1
1,3,6

My existing AWK script does the job but its very slow.
val1, val2,val3 are repeating values and i have "recordstart" before each set of values

I would like to process these files using perl. Idea is to

1. split file into hashes by using "recordstart" as delimiter.
2. process each hash separately.
3. values in 2nd column also need some regular expression job.

Smilie
I know how to read a normal file into hash. My problem here is to split file into chunks and then handle those hash by common variable.

Any hints !
Thanks in advance.
# 2  
Old 01-31-2011
could you show your awk script? just rewriting in a new language won't make it faster, but maybe the logic can be improved.
# 3  
Old 01-31-2011
@corona awk approach is pretty simple

Code:
awk '{if ( $1 == "recordstart" )                                        
              print " ";                                                           
              else                                                                 
              printf $2 ",";}' filename.txt.

Issue is with values like
4E598102'H
255'D
I need to remove 'H and 'D from these values. Sometimes change from HEX to decimal.
processing these value takes much time.

I am under impression that perl will make it bit fast. Also, Using hashes, I can choose fields easily. I dont need to print everything

Last edited by mtomar; 01-31-2011 at 10:25 PM..
# 4  
Old 02-01-2011
It is not a given that Perl will be any faster than Awk. In most cases it won't be.

Here is a code snippet that will get you started with multi-line records from a file:

Code:
#!/usr/bin/env perl

$i=0;
$throw_away=<DATA>;   # read the first record delim...
while (defined($record=<DATA>)) {
    if ($record !~ /recordstart/) {
        $record .= <DATA>; 
        redo unless eof(DATA);
    }
    $record =~ s/^recordstart\Z//m;
    # now you have the full record...
    print "====record $i:\n$record\n";
    $i++;
}
    
__DATA__
recordstart
val1               1
val2               2
val3               4
recordstart
val1               5
val2               6
val3               1
val4               1
recordstart
val1               1 
val2               3
val3               6

An alternate is to use the Perl record separator to help you:


Code:
{ 
    local $/="recordstart\n";
    $throw_away=<DATA>;
    $i=0;
    while ($record=<DATA>) {
        chomp $record;
        $i++;
        # now you have the individual records:
        print "record $i:\n$record";
    }
}


Last edited by drewk; 02-01-2011 at 05:45 AM..
# 5  
Old 02-03-2011
When strictly processing flat files, very often awk is faster than perl, depending on many factors.

One might suggest that you try a different version of awk on the platform you are using.

With an example input file:
Code:
sunt2000/user777$ cat ./test.in
 recordstart
val1               1
val2               2
val3               4
recordstart
val1               5
val2               6
val3               1
val4               1
recordstart
val1               1 
val2               3
val3               6

Your adjusted awk script with some adjustments:

Code:
sunt2000/user777$ cat ./test.sh
awk '
$1 == "recordstart" && FirstLine=="No" { FirstChar="Yes" ; print "" }
$1 == "recordstart" && FirstLine!="No" { FirstChar="Yes" ; FirstLine="No" }
$1 != "recordstart" && FirstChar=="No" { FirstChar="No" ; printf "," $2 }
$1 != "recordstart" && FirstChar!="No" { FirstChar="No" ; printf $2 }
END { print "" }' test.in

The output would look like this:
Code:
sunt2000/user777$ ./test.sh
1,2,4
5,6,1,1
1,3,6

If you are running on a real POSIX compliant platform, you will have multiple versions of awk. The "nawk" tool has more functionality in regard to some built-in variables than "awk" and "/usr/xpg4/bin/awk" has the ability to hold open more simultaneous file handles.

I took the sample data set provided in the thread, repeated it until the input file was 364 lines long, and processed the file 260 times on the "*awk" command line. The aggregate size of all data sets was 1.7MB.

On a slow box, I get the following performance results:

Code:
awk: real: 0m4.21s, 0m4.21s, 0m4.24s
awk: user: 0m4.17s, 0m4.18s, 0m4.21s
awk: sys: 0m0.02s, 0m0.02s, 0m0.02s

/usr/xpg4/bin/awk: real: 0m3.37s, 0m3.45s, 0m3.40s
/usr/xpg4/bin/awk: user: 0m3.33s, 0m3.42s, 0m3.38s
/usr/xpg4/bin/awk: sys: 0m0.02s, 0m0.02s, 0m0.02s

nawk real: 0m1.75s, 0m1.66s, 0m1.72s
nawk user: 0m1.71s, 0m1.63s, 0m1.69s
nawk sys: 0m0.02s, 0m0.02s, 0m0.02s

You can get a 2x-3x boost in speed, by merely adjusting which "*awk" you use.

Removing the 'H and 'D is a simple step in awk. Let's adjust your sample datafile, and repeat it the same number of times in the previous timing example:
Code:
sunt2000/user777$ cat ./test.in3
recordstart
val1               1'H
val2               2'D
val3               4
recordstart
val1               5
val2               6
val3               1'H
val4               1'H
recordstart
val1               1
val2               3
val3               6
...

sunt2000/user777$ cat ./test3.awk
/'H/ { gsub("'H","") }
/'D/ { gsub("'D","") }
$1 == "recordstart" && FirstLine=="No" { FirstChar="Yes" ; print "" }
$1 == "recordstart" && FirstLine!="No" { FirstChar="Yes" ; FirstLine="No" }
$1 != "recordstart" && FirstChar=="No" { FirstChar="No" ; printf "," $2 }
$1 != "recordstart" && FirstChar!="No" { FirstChar="No" ; printf $2 }
END { print "" }

Now, we will adjust the nawk script to remove them, and time the results against over 200 files where each file has thousands of lines:
Code:
sunt2000/user777$ time nawk -f test3.awk test.in3 test.in3 test.in3 ...
 
nawk real: 0m2.39s, 0m2.40s, 0m2.26s
nawk user: 0m2.35s, 0m2.36s, 0m2.24s
nawk sys: 0m0.03s, 0m0.02s, 0m0.02s

The results were just slightly slower adding the stripping.

You can shave off 0.10s more regularly, by avoiding the compares and just force the "gusb" for the 'H and 'D just before the "printf", all time.
Code:
sunt2000/user777$ cat test.awk4
$1 == "recordstart" && FirstLine=="No" { FirstChar="Yes" ; print "" }
$1 == "recordstart" && FirstLine!="No" { FirstChar="Yes" ; FirstLine="No" }
$1 != "recordstart" && FirstChar=="No" { FirstChar="No" ; gsub("'H","") ; gsub("'D","") ; printf "," $2 }
$1 != "recordstart" && FirstChar!="No" { FirstChar="No" ; gsub("'H","") ; gsub("'D","") ; printf $2 }
END { print "" }

sunt2000/user777$ time nawk -f test4.awk test.in3 test.in3 test.in3 ...

nawk real: 0m2.21s, 0m2.26s, 0m2.26s
nawk user: 0m2.18s, 0m2.24s, 0m2.24s
nawk sys: 0m0.02s, 0m0.03s, 0m0.02s

In total, "nawk" is faster than "/usr/xpg4/bin/awk", which is faster than "awk".
Global substitutions can be easily managed in awk.

Last edited by DavidHalko; 02-03-2011 at 06:27 PM.. Reason: remved some unneeded white space
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Programming

awk processing / Shell Script Processing to remove columns text file

Hello, I extracted a list of files in a directory with the command ls . However this is not my computer, so the ls functionality has been revamped so that it gives the filesizes in front like this : This is the output of ls command : I stored the output in a file filelist 1.1M... (5 Replies)
Discussion started by: ajayram
5 Replies

2. Shell Programming and Scripting

Compare values of hashes of hash for n number of hash in perl without sorting.

Hi, I have an hashes of hash, where hash is dynamic, it can be n number of hash. i need to compare data_count values of all . my %result ( $abc => { 'data_count' => '10', 'ID' => 'ABC122', } $def => { 'data_count' => '20', 'ID' => 'defASe', ... (1 Reply)
Discussion started by: asak
1 Replies

3. Shell Programming and Scripting

How to load a hash with a file in Perl

Hi to everybody. I have a script in AWK with a revursive function, when I make the recursive call I'm loosing values in the local variables. So I'm trying to do the script in Perl, but I don't know Perl. I want to load several hashes with the data in a pipe separated file. In AWK it looks... (0 Replies)
Discussion started by: kcoder24
0 Replies

4. Shell Programming and Scripting

perl hash - using a range as a hash key.

Hi, In Perl, is it possible to use a range of numbers with '..' as a key in a hash? Something in like: %hash = ( '768..1536' => '1G', '1537..2560' => '2G' ); That is, the range operation is evaluated, and all members of the range are... (3 Replies)
Discussion started by: dsw
3 Replies

5. Shell Programming and Scripting

Perl Hash:Can not keep hash data in the same order that it was inserted

Can Someone explain me why even using Tie::IxHash I can not get the output data in the same order that it was inserted? See code below. #!/usr/bin/perl use warnings; use Tie::IxHash; use strict; tie (my %programs, "Tie::IxHash"); while (my $line = <DATA>) { chomp $line; my(... (1 Reply)
Discussion started by: jgfcoimbra
1 Replies

6. Shell Programming and Scripting

PERL: reading 2 column data into Hash file

I am trying to read in a 2 column data file into Perl Hash array index. Here is my code. #!/usr/bin/perl -w use strict; use warnings; my $file = "file_a"; my @line = (); my $index = 0; my %ind_file = (); open(FILE, $file) or die($!); while(<FILE>) { chomp($_); if ($_ eq '') { ... (1 Reply)
Discussion started by: subhap
1 Replies

7. Shell Programming and Scripting

Perl file processing

I have an input array like : "SVR1" GRP="EVT_BOX06B" SRID=100 MIN=2 "SVR1" GRP="EVT_BOX06B" SRID=200 MIN=1 "SVR2" GRP="ADM_BOX06B" SRID=100 MIN=1 "SVR1" GRP="EVT_BOX88B" SRID=100 MIN=2 "SVR1" GRP="EVT_BOX88B" SRID=200 MIN=1... (4 Replies)
Discussion started by: deo_kaustubh
4 Replies

8. Shell Programming and Scripting

Processing a file in perl

Qspace ABC Queue doCol: true Queue order: fifo Queue setCol: red Queue order: fifo Qspace XYZ Queue getCol: true Queue order: fifo I need to append every line in this file with Qspace & Queue, so that final o/p shall look like this, Qspace: ABC Queue: doCol Qspace: ABC Queue: doCol... (2 Replies)
Discussion started by: deo_kaustubh
2 Replies

9. Shell Programming and Scripting

awk, perl Script for processing a single line text file

I need a script to process a huge single line text file: The sample of the text is: "forward_inline_item": "Inline", "options_region_Australia": "Australia", "server_event_err_msg": "There was an error attempting to save", "Token": "Yes", "family": "Family","pwd_login_tab": "Enter Your... (1 Reply)
Discussion started by: hmsadiq
1 Replies

10. Shell Programming and Scripting

File processing on perl

Hey everyone ... I wanted to process the contents of a file, as in modify its contents. whats the best way to do it on perl? In more detail I hav to go through the contents of the file, match patterns n then modify the contents of the same file depending on the matching results. Any help is... (2 Replies)
Discussion started by: garric
2 Replies
Login or Register to Ask a Question