[SOLVED] Get strings distributed along up to 3 lines
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Thank you so much. I understand better how it works your code with the explanation. I'll need to see more examples of perl and its syntax
to be able to make more things but I've learned a lot (besides the fact that the help got from all of you).
I've tested the line "my $ha = (length($a)>8) ? Math::BigInt->new("0x$a") : hex($a);" and I've had to add twice this line
inmediately before de line "@result" because if I don't add this line twice I get compilation error in the "else" part of the "while" loop. But it seems is working. I'll test with a real file, the output should be the same, and the time processing a litle bit less I think.
Thank your for the help one more time. You deserve this too certainly . From your last code I was able to modificate it and handle
2 characters in fruit array. Sure there is a better way to do it, but I got it using fruit array and
Pos hash. Main changes in red.
Was I was wondering is how to empty all the elements of fruit array without to create it again with
Array.new(7,""), because fruit.clear removes all elements, I wanted only to change to "" each element, but
anyway, it works in the way I did.
Code:
#!/usr/bin/env ruby -E BINARY
# -*- encoding: utf-8 -*-
BEGIN{ if ARGV[1].nil?
$/="\xff\x77".force_encoding("BINARY")
else
$/="\xff#{ARGV[1].hex.chr}".force_encoding("BINARY")
end
}
fruit = Array.new(7,"")
pos = { "90" => 0,
"91" => 1,
"9a" => 2,
"92" => 3,
"93" => 4,
"96" => 5,
"97" => 6
}
IO.foreach(ARGV[0]){ |l|
line = l.unpack('H*')[0]
next unless line =~ /^(.{6,18})(532064[^f]*).(814[^f]*)/
printf("%d|%s|%s",$1.hex,$2,$3)
if line =~ /05(9.{32,34}.*?)940e(.{28})/
rest = $2
$1.scan(/(9[\dab]).{4}(.{2})(.{8})([^f]*)f*(0[01])(0[01])?/).each{
|y|
arr = y[1..-1].compact.map{
|z|
unless z =~ /^814/
z.hex
else
z
end
}
fruit[pos[y[0]]] = arr.join(",")
}
puts "|" + [fruit.compact,rest.scan(/../).map{|z| z.hex}].join("|")
fruit = Array.new(7,"")
else
puts
end
} if File.exists?(ARGV[0])
Thanks for all the help to all again, very appreaciated!
An old thread, only I found some issue and maybe you can help me to fix it.
To remember, the file contains blocks separated by FF77. Well, the issue I found is that when the next 3 bytes after a block delimiter
have the same sequence FF77, then the block is being skipped.
Examples of this below, the real block delimiters are FF77 in red. But sometimes the first 3 bytes of any block could contain for example 00FF77532064..... And this FF77 in blue is being confused with real delimiter.
How to fix this? maybe a condition to avoid take as delimiter FF77 if it appears inmediate after another FF77?
Another reference is that always appear FF77 + 3 bytes + 532064.
I hope it is not to difficult to handle this issue and you can help me.
What I can imagine at this moment: if you can say for example "the length of a record is at least 15 (or ??) bytes" is an acceptable restriction. In that case we can concatenate lines if they were too short.
Code:
# instead of this:
while ( defined ( my $l = <F> ) ) {
process ($l);
}
# insert this at the beginning of the script
my $MINIMAL_RECORD_LENGTH = 15;
# and modify the while cycle:
while ( defined ( my $l = <F> ) ) {
while (length $l < $MINIMAL_RECORD_LENGTH) {
$l .= $sep;
$l .= <F>;
}
process ($l);
}
(not tested, but I hope it helps)
Of course, you can specify another condition, for example if 532064 comes too early, but actually we cannot avoid delimiters in some cases, that is against the logic of the script (= means should be completely rewritten)
One last question, I was able to do some addition to ruby code, but I was not able to do the same in perl code. I want to store "rest" variable before printing the output to compare with a string.
I mean, string to compare would be for example compare=||2,13,456|43(2\|\|8)|2|1| and if rest = compare then
Rest=rest+"|A" and if rest is different than compare, then rest=rest + "|B”
I am with pan in that you will need to know what your criteria is for ignoring a split before you can write code to compensate, ie just how far apart will be considered too far or not far enough??
Not sure I follow the new question? You can assign 'rest' to another variable and compare to anything you like so I am not following the exact issue for this part?
The less size a block could have is 3+8+8 bytes = 19 bytes. Maybe with that condition could be fix the issue, with 15 as mentioned by pan64 could work too.
Regarding my other question, I was able to modify the part "puts "|" + [fruit.compact,rest.scan(/../).map{|z| z.hex}].join("|")" in your code and assign that to "rest", then, before print "rest", I compare "rest" with string "compare". Compare variable has a regex inside (in red).
So, for ruby I was able to do it, but for perl I haven't had success to replicate the push part "push @result, join '|', map ( hex, unpack("(A2)*", $rest) );" similar to what I did in ruby.
The lines below in blue are those I added in ruby code and works.
In perl script I understand that the following line prints "result" variable concatenated with "rest" variable and putting in the same operation the delimiter "|".
The issue is how to replace the part "join '|', map ( hex, unpack("(A2)*", $rest) )" and store it in "rest". Once I have the content stored in "rest", I would be able to compare with string "compare".
Regarding to the other question, would be something like this?
Code:
MINIMAL_RECORD_LENGTH = 15
IO.foreach(ARGV[0]){ |l|
line = l.unpack('H*')[0]
if line.length < MINIMAL_RECORD_LENGTH do
line = "FF77" + line
end
##
Original code
##
} if File.exists?(ARGV[0])
push, join and map will not print anything, that line only collects the result in the array @result.
$rest = join '|', map ( hex, unpack("(A2)*", $rest);
should work,
push @result, $rest; # or any other variable
also (do not forget to declare: my $rest)
but actually I do not really understand what do you need.
Actually I want to compare elements from 3 to N of array @result. I think I almost near since I found this way.
Code:
$z= join ("|", @result[ 3 .. $#result);
That command it seems to work to store the string I need in $z. I only want now to compare that string in $z with 3 strings that only are different in number in red, like below:
I finally was able to make the comparison in perl in the long way (if.. else) since I was not able to make it short way, since
I don't know how to assign the pattern to a variable. I did like below.
In ruby I was able to do it in short way like below:
Code:
z = "|" + [fruit.compact,rest.scan(/../).map{|z| z.hex}].join("|")
compare=/2,13,8147526905,0\|\|\|12,13,8147526905,1,1\|\|12,13,814752695(59|65|86),0\|\|1\|2\|1\|2\|1\|0\|1\|255\|255\|255\|2\|1\|2\|1/
z = ( z=~ compare ? z . "|A" : z . "|B" )
Regarding the other question, the suggestion you said me of modify the "while loop" in post #112 it seems to work, the only issue
is that the number of th first column is not correct, should be the 3 first bytes after the delimiter FF77 converted to decimal, but
is being printed a big number. It seems is taking more characters when converting from hex to dec in first column.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.