in reply to Proper use of split
Hi, th3j4ckl3.
I'm impressed by what you've accomplished, having decided to learn Perl just this week! I think you've done quite well.
By the great responses to your query, you may have noticed the multiple solutions to your question. You may also know that this is not at all unusual. Although I think using a Perl Module to parse the data string is an excellent suggestion for some time in your learning, I'm more inclined to think it's more pedagogically sound--at this point, at least--to code it yourself, especially since you've already practically solved this issue.
Give this, here's another solution that primarily uses your approach:
use Modern::Perl; my $tstatcollect = '/home/julian/tstatcollect'; open my $file, "<$tstatcollect" or die "Can't open $tstatcollect: $!"; my $data = <$file>; close $file; my @dataElem = ( split ',', $data )[ 0 .. 3 ]; foreach (@dataElem) { my ( $lable, $value ) = /"(.*)":(.*)/; say "\u$lable: $value"; }
Output
Temp: 70.00 Tmode: 2 Fmode: 0 Override: 0
Setting up a programming environment to help debug scripts is invaluable and time saving. The use Modern::Perl pragma includes both use strict; and use warnings;--which you'll often see at the top of scripts. I encourage you to always include these in your scripts.
You'll notice the or die after the open call. This handles errors, just in case your open fails.
Since there's only one line in your file, I chose to not use while, but rather just read that single line into a variable. I liked your splitting on a comma. Enclosing split within parentheses creates a list, and the [ 0 .. 3 ] notation requests only elements 0-3 of that list, which are placed into @dataElem.
Now, we iterate over those split elements, using a regex with captures to grab the label and value from each element. (Side note: instead of assigning the capture results to $lable and $value, we could have used $1 and $2, which directly correspond to the captured contents.)
Finally, we print with an "\n" (say) the result, using \u to uppercase the first letter of the label.
Hope this helps!
Update:
Give your updated data string and wanting to display all fields, you can make the following change in the above script to handle the time elements:
my @dataElem = ( split ',', $data ); foreach (@dataElem) { next if !( my ( $lable, $value ) = (/("time":{"?)*"(.*)":([^}]+)/)[ 1 +, 2 ] ); say "\u$lable: $value"; }
Output (given your new string):
Temp: 75.50 Tmode: 2 Fmode: 0 Override: 0 Hold: 0 T_cool: 75.00 Tstate: 0 Fstate: 0 Day: 4 Hour: 13 Minute: 49
It's an ugly regex, but it's trying to match three items, where the first is optional. Notice the [ 1, 2 ] notation again, which was present in the original script. The matching creates a list, and we're requesting the last two elements of the list--provided there *is* a match.
With you now wanting to use all the fields of your data string and having updated its format, I think kennethk's use of the JSON Module is an excellent solution for you to consider.
|
|---|