Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

string matching 2

Status
Not open for further replies.

keid

Technical User
Aug 8, 2006
22
DE
Hello, I have a file like that

FUNCT_CURVE curve_id_num 5
abs coord
1 4
2 5
6 7
7 9
8 10
END

Small explanation: I have a text file I want to read from it and store the values of the abscissa and coordinate in a hash or array... note next to the line FUNCT_CURVE the number stands for how many lines of abs and coord we have.
of course in the file i have there is several functions with different curve id.

thanks for the help in advance and any info needed, please let me know.

PS: I used substrings and pattern matching, but what is hard for me is going in the loop and storing these values

foreach $data (@inp_data)
{

if($data=~ m/^FUNCT /)
{
$function_id= substr("$data", x, y);
$all_functions{$function_id}=$function_id; # used for sorting them as hash....
 
is that how the entire file looks? Is there more than one instance of FUNCT_CURVE followed by some lines in the file?
 
yes; the FUNCT_CURVE is repeated several times according to the curve_id_num. so the file contains other info like that


something 1 4 6 7
.
.


FUNCT_CURVE 234 5 #234 is just the name of the curve num
abs coord
1 4
2 5
6 7
7 9
8 10
END

something else

FUNCT_CURVE 235 2#2 is the num of abs and coord
abs coord
1 4
2 5
END
 
Hi keid,

Please find one way to do it below. The basic idea is to read in everything first from data.txt and to throw away lines which we know aren't data.

The key for you is marked in line # A. $content contains, e.g., "1 4" as the first element. I split it here into a list with just two elements ($x, $y). The splitting pattern is \s+, which means one or more white spaces (space, tab etc.).

Next I assign it to the hash %data, as you want. Because your data represent a function by this (mathematical) definition the abscissa values are unique. Else you would lose data.

Finally I just print %data for your control purposes.

Unfortunately I don't entirely understand how all your data are organized. But this should give you a start ;-)

Code:
# this works for ActivePerl; add your #! here for other Perl versions
use strict;
use warnings;

my $file = "data.txt";	# filename
my @content;		# content we'll retrieve
my %data;		# your final xy-pairs

open F, $file or die "cann't open $file $!\n";
@content = <F>;		# read all in
close F;

shift @content;		# remove 1st line (FUNCT_CURVE ...)
shift @content;		# remove 2nd line (abs coord)
pop @content;		# remove last line (END)

foreach my $content (@content) {
	my ($x, $y) = split /\s+/, $content;  # A
	$data{$x} = $y;
}

foreach my $x (sort keys %data) {	# see the result
	print "$x  $data{$x}\n";
}


Hope this helps.

Kind regards,
Michael

(From: Michaels Perl-services, )
 
Thanks Michael

Actually in my file, there is many curve functions with different curve ID, and next to this ID it specifies for me how many lines before the END.

so i need to print on the output file something like that

Curve number xxx
abs coord
.
.
.

 
Hello keid,

Can you please post the first few lines of a file with several curves in it?

The number of lines you can read in a similar way as you split the data. E.g. you can do it like this:

Code:
my $first = shift @content;        # remove 1st line
my ($dummy, $num) = split/curve_id_num/, $first;

Hope this helps.

Kind regards,
Michael

(From: Michaels Perl-services, )
 
if what you are doing is making a new file you don't need to use an array or hash unless you needed to do something with the data before writing to the new file. Here is one way doing a straight conversion:

Code:
use strict;
use warnings;
my $flag = 0;
open(IN,'<data.txt') or die "Can't open data.txt: $!";
open(OUT,'>results.txt') or die "Can't open results.txt": $!";
while(<IN>){
   ($flag = 0 && next) if /^END$/; 
   print OUT $_ if $flag==1;
   if (/^FUNCT_CURVE\s+(\d+)\s+(\d+)/) {
      $flag = 1;
      print OUT "Curve number $1\n";
   }
}
close(IN);
close(OUT);
 
I think this is basically what you're looking for. There's plenty of room for improvement, specifically you could implement a little more error checking; but this should give you a good start.
Code:
my %records;
while (<DATA>) {
    if (/FUNCT_CURVE\s+(\d+)/) {
        $_ = <DATA>;    # Skip headers

        while (<DATA>) {
            last if /END/;    #End of record
            my ($x, $y) = split;
            $records{$1}{$x} = $y;
        }
    } else {
        next;
    }
}
    
foreach my $name (sort {$a <=> $b} keys %records) {
    print "Curve Name: $name\n";
    print join("\t", "abs", "coord"), "\n";

    foreach my $key (sort {$a <=> $b} keys %{$records{$name}}) {
        print join("\t", $key, $records{$name}{$key}), "\n";
    }

    print "\n";
}

__DATA__
FUNCT_CURVE  234 5 #234 is just the name of the curve num
abs coord
1   4
2   5
6   7
7   9
8   10
END

something else

FUNCT_CURVE  235 2#2 is the num of abs and coord
abs coord
1   4
2   5
END
 
Thanks Guys alot, it was really helpful. I am new to perl only one month practice with oreilly learning perl. Can you give me advice about perl books?
 
I have another problem with the forward slash as in this example

FUNCT / 10516 0 1. 1. .0 .0
NAME K MOBIL
-3. .0
.0 .0
.001 500.
3. 1000.
END
FUNCT / 10517 0 1. 1. .0 .0
NAME K MOBIL
-3. -1000.
-.001 -500.
.0 .0
3. .0
END


I need to ouput the file as


*DEFINE_CURVE_TITLE
K MOBIL
10516 0 1. 1. .0 .0
-3. .0
.0 .0
.001 500.
3. 1000.


etc...

 
The forward slash if fixed with (\S), but now i need to store the title K MOBIL in addition to the values 0 1. 1. .0 .0
next to the 10516 .
 
You're going to have to change the data structure a bit to keep track of the extra information. Try something like this:
Code:
my %records;
while (<DATA>) {
    if ($_ =~ m!FUNCT\s+/\s+(\d+)([\d\.\s]+)\s+$!) {
        my ($label, $values) = ($1, $2);
        $records{$label}{values} = $values;

        $_ = <DATA>;    # Get Name;
	my ($name) = m/NAME\s+(.+)\s+$/;
        $records{$label}{name} = $name;

        while (<DATA>) {
            last if /END/;    #End of record
            my ($x, $y) = split;
            $records{$label}{data}{$x} = $y;
        }
    } else {
        next;
    }
}

foreach my $label (sort {$a <=> $b} keys %records) {
    print '*DEFINE_CURVE_TITLE', "\n";
    print "$records{$label}{name}\n";
    print "$label\t$records{$label}{values}\n";
    
    foreach my $key (sort {$a <=> $b} keys %{$records{$label}{data}}) {
        print join("\t", "\t", $key, $records{$label}{data}{$key}), "\n";
    }

    print "\n";
}
 
Dear rharsh

I dont understand what do you mean by these lines, if you can give me brief explanation of how to address each element of the hash

$records{$label}{name} = $name;
records{$label}{data}{$x} = $y
$records{$label}{data}{$key}
%{$records{$label}{data}})

Any useful reference book u can advice!! many thanks
 
The lines above are what could be called a multi-dimensional hash. Perl uses what it calls references to achieve these types of data structures.

The first three tutorials on this page go over references:



References may be confusing if you are still early in the learning process.
 
The first two in the list from Kevin's link are good places to start.

I don't have a copy of the Learning Perl handy, but doesn't it have a little bit on references? Maybe not. I know the Programming Perl book does - you wanted a suggestion on another book, I'd suggest picking that one up.
 
I used this code for searching for keyword, probably not a good way but I managed to get some info until i get stuck with the FUNCT END

@pc_file_original= <DATA>;


$i = 0;
foreach (@pc_file_original)
{
chomp($_);

$_ =~ s/\s+$//;

if(!(($_=~ m/^\$/) or ($_=~ m/^\#/)))
{
$pc_data[$i] = $_;
$i += 1 ;
}
}
foreach $data (@pc_data)
{
then i continued to search for several keywords, of which to search for FUNCT

if($data=~ m/ FUNCT....
$function_id= substr("$data", 9, 8);
all_functions{$function_id}=$function_id;


so i could not make changes to ur file to let it work in my foreach loop. Please can you help me in adjusting the code to fit in my loop. I hope my question was clear .

 
Please can you help me in adjusting the code to fit in my loop.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top