LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-27-2008, 05:11 PM   #1
hardbop200
LQ Newbie
 
Registered: Jul 2005
Location: Texas
Distribution: Debian, dyne:bolic
Posts: 11

Rep: Reputation: 0
perl - arrays


Hello all,

I am working on a project where I read incoming data from a RFID reader, and spit the data into a database. The data coming from the device looks like this:

Tag:4845 4930 3030 3030 3030 3033, Disc:2008/10/27 14:37:02.015, Last:2008/10/27 14:37:02.015, Count:1, Ant:0, Proto:2

My script reads this data into an array, splitting on the comma:

Code:
#!/usr/bin/perl -w
use strict;
use warnings;
use IO::Socket;

my $port = 4000;
my @data;
my $server = IO::Socket::INET->new (
	Proto => 'tcp',
	LocalPort => $port,
	Listen => SOMAXCONN,
	);

print "Server running on port $port...\n";
while (my $connection = $server->accept) {
	print "Client connected at ", scalar(localtime), "\n";
	while (<$connection>) {
		@data = split (/,/);
		print @data;
	}
	close $connection;
	print "Client disconnected\n";
}
My problem is this: I *know* that I need only 6 fields in my array: tag, disc, last, count, ant and proto; however, the script doesn't allow me to define where an array stops and a new one begins. For example, I would like to do something like this:

my @data = $tag, $disc, $count...etc

So that when this part of the script reads:

Code:
while (<$connection>) {
		@data = split (/,/);
		print @data;
	}
...it stops on the 6th field and creates a new array.

Is this making sense? All of the textbook examples have the array's data defined at the beginning of the script, which obviously isn't going to happen here; I need to insert the data as it comes in, and access it (so I can then insert it).

Help!

Thanks,

Josh

Last edited by hardbop200; 10-27-2008 at 09:36 PM. Reason: added code tags
 
Old 10-27-2008, 05:30 PM   #2
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Rocky 9.2
Posts: 18,362

Rep: Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751Reputation: 2751
Actually, its not entirely clear to me, but I'll have a go.
Are you getting 6 fields at a time into the array, or 1 field at a time ie a 6-field rec, or an unending stream of individual fields, 1 at a time that happen to be csv?
What do you need to do with the data?
Are you going to process each array / 6-fields as they arrive, or are you planning to store a load of them and process them later?

PS please use code tags, it makes it easier to read your code.
 
Old 10-27-2008, 07:50 PM   #3
keefaz
LQ Guru
 
Registered: Mar 2004
Distribution: Slackware
Posts: 6,552

Rep: Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872Reputation: 872
Maybe insert a newline character after Proto:xx
Code:
while (<$connection>) {
    s/(Proto:\d)/$1\n/g;
    print;
    # if you need data to process...
    @data = split (/\n/);
}
Edit: not sure it is a good idea with a live stream from connection...
Better to loop and check end of infos blocks with /Proto:\d/ or similar

Last edited by keefaz; 10-27-2008 at 07:56 PM.
 
Old 10-27-2008, 08:08 PM   #4
estabroo
Senior Member
 
Registered: Jun 2008
Distribution: debian, ubuntu, sidux
Posts: 1,126
Blog Entries: 2

Rep: Reputation: 124Reputation: 124
A q&d way of doing this would be to have a counter that increases whenver you see the proto tag and push the data into an anonymous array in a hash

kind of like

Code:
$counter = 0;
while (<$connection>) {
    @data = split(/,/);
    foreach $item (@data) {
        push @{$h_data{$counter}}, $item;
        if ($item =~ /Proto: /) {
            $counter++;
        } 
    }   
}
# counter ends up with the total number of records read
Then to access any particular record
Code:
@data = @{$h_data{$record_number}};
$tag = $data[0];
Alternatively you could use an anonymous hash and then pull out the information by name, just split each data item on the :
Code:
while (<$connection>) {
    @data = split(/,/);
    foreach $item (@data) {
        ($key, $val) = split(/:/,$item,2);
        $h_data{$counter}->{$key} = $val;
        if ($item =~ /Proto: /) {
            $counter++;
        }
    }
}
Now if it's a continuous stream then instead of just incrementing the counter you could call a function with the data, just make sure you delete the entry when your finished so you don't run out of memory.
 
Old 10-27-2008, 09:35 PM   #5
hardbop200
LQ Newbie
 
Registered: Jul 2005
Location: Texas
Distribution: Debian, dyne:bolic
Posts: 11

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by estabroo View Post
Now if it's a continuous stream then instead of just incrementing the counter you could call a function with the data, just make sure you delete the entry when your finished so you don't run out of memory.
Thanks, I'll try all of these suggestions and see which one works out best.

You were right about the continuous stream; I'll give this approach a try and see if I can figure this out and I'll post my results.

Thanks for all of the information, and apologies for my post being a little hazy...I'm very new to Perl, just trying to use it to "get the job done!"

Thanks again,

Josh
 
Old 10-28-2008, 03:24 AM   #6
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
The following example might help:

Code:
sergei@amdam2:~/junk> cat -n arrays_and_vars.pl
     1  #!/usr/bin/perl -w
     2
     3  use strict;
     4
     5  my @array = (0, 1, 2, 3, 4);
     6
     7  my ($field0, $field1, $field2) = @array;
     8
     9  warn "\$field0=$field0 \$field1=$field1 \$field2=$field2";
sergei@amdam2:~/junk> ./arrays_and_vars.pl
$field0=0 $field1=1 $field2=2 at ./arrays_and_vars.pl line 9.
sergei@amdam2:~/junk>
 
Old 10-28-2008, 10:46 AM   #7
hardbop200
LQ Newbie
 
Registered: Jul 2005
Location: Texas
Distribution: Debian, dyne:bolic
Posts: 11

Original Poster
Rep: Reputation: 0
OK, lots of good stuff happening with this script!

Here's what ended up working:

Code:
while (my $data = <$connection>) {
		foreach (split(/\n/,$data)) {
			#print $data;
			my ($field0, $field1, $field2, $field3, $field4, $field5) = (split(/\,/,$_))[0,1,2,3,4,5];
This returns nicely formatted columns like:

Code:
Tag:4845 4930 3030 3030 3030 3032
Now I would like to run each item ($field0, $field1, etc.) through another parser in a subroutine that will split each column by the colon ":", with the first part of the split being $key (which will be discarded), and $value (which will actually be inserted; Here is the part of the code that sends $field0...$field5 to the parser:

Code:
my ($field0, $field1, $field2, $field3, $field4, $field5) = (split(/\,/,$_))[0,1,2,3,4,5];
			&parse_text (@data);
			print "$field0\n";
...and here is the parser:

Code:
sub parse_text {
	foreach (@_) {
		my ($key, $var) = (split(/:/,@_))[0,1];
		$var = @_;
		return @_;
	}
}
Basically, I want to send the parser $field0, split it, assign the result of $var = $field0, and return the new-and-improved $field0 back to my main program. Yet, the $var = @_ doesn't seem to work, and return @_ sure doesn't work. Any ideas?
 
Old 10-28-2008, 10:56 AM   #8
hardbop200
LQ Newbie
 
Registered: Jul 2005
Location: Texas
Distribution: Debian, dyne:bolic
Posts: 11

Original Poster
Rep: Reputation: 0
I spoke too soon, this works great:

Code:
#!/usr/bin/perl -w
#use strict;
use warnings;
use IO::Socket;

my $port = 4000;
my $server = IO::Socket::INET->new (
	Proto => 'tcp',
	LocalPort => $port,
	Listen => SOMAXCONN,
	);

print "Server running on port $port...\n";
while (my $connection = $server->accept) {
	print "Client connected at ", scalar(localtime), "\n";
	while (my $data = <$connection>) {
		foreach (split(/\n/,$data)) {
			#print $data;
			#my ($field0, $field1, $field2, $field3, $field4, $field5) = (split(/\,/,$_))[0,1,2,3,4,5];
			my (@data) = (split(/\,/,$_))[0,1,2,3,4,5];
			foreach (@data) {
				my ($key, $var) = (split(/:/,$_))[0,1];
				print "$var\n";
				}
			}
	}
	close $connection;
	print "Client disconnected\n";
}
 
Old 10-28-2008, 11:20 AM   #9
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by hardbop200 View Post
I spoke too soon, this works great:

Code:
#!/usr/bin/perl -w
#use strict;
use warnings;
use IO::Socket;

my $port = 4000;
my $server = IO::Socket::INET->new (
	Proto => 'tcp',
	LocalPort => $port,
	Listen => SOMAXCONN,
	);

print "Server running on port $port...\n";
while (my $connection = $server->accept) {
	print "Client connected at ", scalar(localtime), "\n";
	while (my $data = <$connection>) {
		foreach (split(/\n/,$data)) {
			#print $data;
			#my ($field0, $field1, $field2, $field3, $field4, $field5) = (split(/\,/,$_))[0,1,2,3,4,5];
			my (@data) = (split(/\,/,$_))[0,1,2,3,4,5];
			foreach (@data) {
				my ($key, $var) = (split(/:/,$_))[0,1];
				print "$var\n";
				}
			}
	}
	close $connection;
	print "Client disconnected\n";
}
Whatever you are writing, "while (my $data = <$connection>)" is bad,
it should rather be "while(defined(my $data = <$connection>))".

It's written in the manual, FAQ, etc.

The point is relationship between TRUE, FALSE, 0, undef.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to compare two lists (arrays) in perl WindowBreaker Programming 13 04-24-2008 03:01 AM
Perl substitution with arrays cramer Programming 2 08-14-2006 11:07 PM
perl: concatenate arrays jrtayloriv Programming 2 01-23-2005 07:13 AM
PERL : Arrays confusing? fredgt Programming 3 12-19-2004 08:24 AM
arrays in perl BBQ_Matt Programming 3 09-23-2003 07:45 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:02 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration