469,330 Members | 1,246 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,330 developers. It's quick & easy.

Perl : HEX parameter handling

Hi,

Please tell how to write :A script which reads a file and search for some words like ABC or FGH in the file text and put some variable after their occurance.That variable is configurable HEX parameter which can be configured through config file or can be given as a command line parameter.

Thanks
Oct 17 '06 #1
13 9901
miller
1,089 Expert 1GB
<RANT>
No Thanks

If you really would like some help you should appear to have put at least some effort into the problem before posting on this forum. Show us some code. Show us that you have at least thought about possible solutions and have simply run into a problem. All you've done thus far is demonstrated that you can copy and paste a homework assignment.
</RANT>
Oct 18 '06 #2
Hi All ,

I am able to write some code for the above said problem.
The code is given below .
But i still have 2 problems.

1. There is occurance of some blank lines when i execute the script, I need to remove those blank lines. and

2. I need to compare the two lines of a given file ,say

BHS|^~\&|NVA |
MSH|^~\&|NVA |
MSH|^~\&|NVB |
EVN|P03|20060702 |
PID| |5360738 |

If there is occurance of MSH segment after BHS segment then change the first occurance of MSH to MSD.


Code:

#!/usr/local/bin/perl -w


# This Perl program in classic programming style changes
# the string "headerOld" to "headerNew" in all files
# specified on the command line.

@headerOld=('BHS','BTS','FTS');
@headerNew=("\nABHS","\nBBTS","\nFFTS");


for ($i=0;$i<3 ;$i++) {

$nchanges = 0;
undef $/;

foreach $file (@ARGV) {
if (! open(INPUT,"<$file") ) {
print STDERR "Can't open input file $bakfile\n";
next;
}

# Read input file as one long record.
$data=<INPUT>;
close INPUT;

# Replaces the headerOld with headerNew in the $data content.
if ($data =~ s/$headerOld[$i]/$headerNew[$i]/gi) {
$bakfile = "$file.bak";
# Abort if can't backup original or output.
if (! rename($file,$bakfile)) {
die "Can't rename $file $!";
}
if (! open(OUTPUT,">$file") ) {
die "Can't open output file $file\n";
}
$data =~ s/\n+/\n/g;

print OUTPUT $data;
close OUTPUT;
$nchanges++;

}
else { print STDERR "$file not changed\n"; }
}
}

print STDERR "$nchanges files changed.\n";

exit(0);
Oct 26 '06 #3
miller
1,089 Expert 1GB
Some initial comments and changes to your code:

1) Format your code. It helps us read it faster, and even more importantly, it will help you as well.

2) You should perform all transformations on each file, instead of each transformation on all files. In other words, limit hte number of times that you are opening and closing a file. Currently, you open and close each file for every transformation. Along with slowing down your performance by an order of magnitude, this also adds risk with regard to race conditions. Avoid this.

3) "use strict;" Always include this line in your file. It will help you out more than you could ever dream, although I see that you are using -w as well, which is good. I found one variable misspelling immediately upon making this change.

4) "undef $/;" is bad. use "local $/;" instead. Read about why at http://perldoc.perl.org/perlvar.html (Search for $/)

5) Instead of "print STDERR", try using "warn" instead. See http://perldoc.perl.org/functions/warn.html

6) What's with the return characters in @headerNew? Do you really want those to be there? I'm guessing not.

7) $i<3 is a bad idea. Instead use the number of elements in @headerOld as your limitting factor.

8) exit(0) is nice to do, but it's kind of redundant. Just do 1;\n\n__END__

Expand|Select|Wrap|Line Numbers
  1. #!/usr/local/bin/perl -w
  2.  
  3. # This Perl program in classic programming style changes
  4. # the string "headerOld" to "headerNew" in all files
  5. # specified on the command line.
  6.  
  7. use strict;
  8.  
  9. my @headerOld = ('BHS','BTS','FTS');
  10. my @headerNew = ('ABHS','BBTS','FFTS');
  11.  
  12. my $nchanges = 0;
  13.  
  14. foreach my $file (@ARGV) {
  15.     open(INPUT, "< $file") or warn("Can't open input file $file\n"), next;
  16.  
  17.     # Read input file as one long record.
  18.     local $/;
  19.  
  20.     my $data = <INPUT>;
  21.     close INPUT;
  22.  
  23.     my $hasChanged = 0;
  24.  
  25.     for (my $i=0; $i<@headerOld; $i++) {
  26.         # Replaces the headerOld with headerNew in the $data content.
  27.         $hasChanged += $data =~ s/$headerOld[$i]/$headerNew[$i]/gi;
  28.     }
  29.  
  30.     if ($hasChanged) {
  31.         # Wippee!
  32.         my $bakfile = "$file.bak";
  33.  
  34.         # Abort if can't backup original or output.
  35.         rename($file, $bakfile) or die "Can't rename $file $!";
  36.  
  37.         open(OUTPUT, "> $file") or die "Can't open output file $file\n";
  38.  
  39.         $data =~ s/\n+/\n/g;
  40.  
  41.         print OUTPUT $data;
  42.         close OUTPUT;
  43.  
  44.         $nchanges++;
  45.  
  46.     } else {
  47.         warn "$file not changed\n";
  48.     }
  49. }
  50.  
  51. warn "$nchanges files changed.\n";
  52.  
  53. 1;
  54.  
  55. __END__
  56.  
Ok, now that we've gone through all that cleanup, we come to your real problem. You currently describe two different things that you're trying to accomplish:

Goal 1) There is occurance of some blank lines when i execute the script, I need to remove those blank lines. and

Are these blank lines "added" by your script? or are they originally in the text file and you want to parse them out? I believe that if the former is true, then I've fixed your problem by editing @headerNew.

Goal 2) Duplicate MSH

I need to compare the two lines of a given file ,say

BHS|^~\&|NVA |
MSH|^~\&|NVA |
MSH|^~\&|NVB |
EVN|P03|20060702 |
PID| |5360738 |

If there is occurance of MSH segment after BHS segment then change the first occurance of MSH to MSD.
I believe you meant:

If there are TWO MSH segments after a BHS segment then change the first occurance of MSH to MSD.

Is this true?


Goal 3) Direct translation of some text

Change the following values:
'BHS' => 'ABHS'
'BTS' => 'BBTS'
'FTS' => 'FFTS'

Do you want to change all of these values regardless of when they occur? Do these values only occur at the beginning of a record (or line)?

Clarify these questions and I'll help you further.
Oct 26 '06 #4
First of all I would like to thank you ,Miller for your help…
It has boosted up my interest to put more efforts in learning and working with PERL.

Let me explain your findings one by one:

Goal 1) There is occurance of some blank lines when i execute the script, I need to remove those blank lines. and

Note: Yes these lines are added when I run the script.

Goal 2) Duplicate MSH

I believe you meant:

If there are TWO MSH segments after a BHS segment then change the first occurance of MSH to MSD.

Is this true?

Note: In the message there could be more then two MHS as well. But the first occurrence after BHS need to be changed .say MSH to /rMSH.
Sample message:

BHS|^~\&|NVA |
MSH|^~\&|NVA |
MSH|^~\&|NVB |
EVN|P03|20060702 |
PID| |5360738 |
BHS|^~\&|NVA |
MSH|^~\&|NVA |
MSH|^~\&|NVB |
MSH|^~\&|NVA |
MSH|^~\&|NVB |
EVN|P03|20060702 |
PID| |5360738 |

Goal 3) Direct translation of some text

Change the following values:
'BHS' => 'ABHS'
'BTS' => 'BBTS'
'FTS' => 'FFTS'

Do you want to change all of these values regardless of when they occur? Do these values only occur at the beginning of a record (or line)?


Note: Yes these values are changed regardless of when they occur.
There could be thousands of MSH and Hundreds of BHS.

The message is read as different records and that is achieved by doing the above replacements , they act as record separators.
Say …If I replace BHS by \nBHS the there is addition of “0d 0a ” in hex.
And "0d 0a" becomes the record separotor.
The same way I need to change for FTS , BTS and the MSH(first occurrence after BHS).
The separator is need to be kept same for all the replacements.
Oct 27 '06 #5
Please help me out with the MSH replacement function....
I am not able to figure it out.

Sorry but my code is not working at all...
Oct 28 '06 #6
miller
1,089 Expert 1GB
Hi All ,
2. I need to compare the two lines of a given file ,say

BHS|^~\&|NVA |
MSH|^~\&|NVA |
MSH|^~\&|NVB |
EVN|P03|20060702 |
PID| |5360738 |

If there is occurance of MSH segment after BHS segment then change the first occurance of MSH to MSD.
I'm editing code for you right now. Should only take me a 10 minutes. I'm still unsure why you said first in the above statement though. In the end I'm going to end up making up my own rules concerning what you might have intended, and you can simply use the code as starting point since I really don't understand your specification.
Oct 30 '06 #7
miller
1,089 Expert 1GB
Expand|Select|Wrap|Line Numbers
  1. use File::Basename qw(dirname);
  2. use File::Temp;
  3. use POSIX qw(strftime);
  4.  
  5. use strict;
  6.  
  7. # Goal 1
  8. # - If there is an MSH segment immediately after a BHS segment, then replace it with MSD
  9. # - Note: Segments are defined as the letters beginning a line
  10.  
  11. # Goal 2
  12. # - Rename Segments to a new type.
  13. my %translate = (
  14.     'BHS' => 'ABHS',
  15.     'BTS' => 'BBTS',
  16.     'FTS' => 'FFTS',
  17. );
  18. my $translateKeys = join('|', keys %translate);
  19.  
  20. my $nchanges = 0;
  21.  
  22. foreach my $file (@ARGV) {
  23.     open(INPUT, "< $file") or warn("Can't open input file $file\n"), next;
  24.  
  25.     print "processing: $file\n";
  26.  
  27.     # This assures that the new file will actually be unique.
  28.     my $tmp = new File::Temp(
  29.         DIR        => dirname($file),
  30.         UNLINK    => 0,
  31.         SUFFIX    => '.tmp',
  32.     );
  33.  
  34.     print "\tSaving new data to: " . $tmp->filename . "\n";
  35.  
  36.     my $changes = 0;
  37.  
  38.     # Process the file one line at a time
  39.     while (my $queue = <INPUT>) {
  40.         # Might end up with queue of lines to process
  41.         my @lines = ($queue);
  42.  
  43.         # Begins with BHS (Goal 1 Code)
  44.         # - Note: Cannot be at the end of the file.
  45.         if ($queue =~ m/^BHS/ && ! eof(INPUT)) {
  46.             $queue = <INPUT>;
  47.             $changes += $queue =~ s/^MSH/MSD/;
  48.             push @lines, $queue;
  49.         }
  50.  
  51.         # Process Possibly Multiple lines
  52.         foreach my $line (@lines) {
  53.             # Translate segments (Goal 2 Code)
  54.             $changes += $line =~ s/^($translateKeys)/$translate{$1}/g;
  55.  
  56.             # Output Results.
  57.             print $tmp $line;
  58.         }
  59.     }
  60.  
  61.     close(INPUT) or die "close $file: $!";
  62.     $tmp->close() or die "close $tmp: $!";
  63.  
  64.     print "\tChanges Found: $changes\n";
  65.     $nchanges++ if $changes;
  66.  
  67.     # Backup Old File
  68.     # - Alternatively, you can choose to just delete the old file.
  69.     # unlink($file) or die "unlink $file: $!";
  70.     my $bakfile = $file . strftime(".%Y%m%d.%H%M%S", localtime()) . '.bak';
  71.     rename($file, $bakfile) or die "can't rename $file: $!";
  72.  
  73.     # Move Processed Results to old file location
  74.     rename($tmp->filename, $file) or die "can't rename $tmp to $file: $!";
  75. }
  76.  
  77. warn "$nchanges files changed.\n";
  78.  
  79. 1;
  80.  
  81. __END__
  82.  
The above code does many of the things that you needed. Even if this doesn't fit your specifications exactly, it at least should give you an example of a better way of processing files line by line and as a group of lines. I've also taken into account many things that your code was failing to do. I leave it as an exercise for yourself to determine what those changes were and why.

Additionally, I also added dependencies to three CPAN modules. I believe that those are all part of the default installation of perl, but if not, then they are easily added from http://cpan.perl.org. Alternatively, they could be removed from the script entirely, but you would have to discover for yourself how to do this.
Oct 30 '06 #8
Thanks Miller.

I used first becoz ur the first one who has replied to my first post on any forum.
This is my first experience of being associated with any group online.
Morover very first experience working with PERL.

Thanks again ...

I m going to finish the exercise given by u. If any problem persists i will again get back to u.

regards...
Oct 30 '06 #9
Hi Miller,

This is in reference to my post #3, the only thing i wasn't able to add is the liberty of replacing MSH(first occurance after BHS in it) otherwise things are working fine .
The changes u made in post #4 are the best suitable for me.

In code we can the scenerio as :

my @headerOld = ('BHS','BTS','FTS');
my @headerNew = ("\nBHS","\nBTS","\nFTS");

In the same way i want to replace MSH(first occurance after BHS ) with "\nMSH".

The replacement prefix value can be anything like "\n\t" etc.

Please help me with the current funtionality addition.The test data can be same as in post post #5.

It is my mistake that i am not able to write the best explainatory specification for the problem.

regards...
Oct 30 '06 #10
Hi
The functionality of changing MSH is required at every step not the only the 1st occurance after BHS...so done. Thanks

Some more complexities i am finding in my script.

1) Can i parse any HEX character in perl and check its value and replace by a different HEX in any record.

e.g This is Perl scripts developer community.

In any HEX editor if i open this message then i found 20 against space .
Question :How can i search for a HEX character in any given file.

2) The HEX replacement should be done between given segments only (say between FHS[end of record ] separated by HEX 0a and BHS OR BHS [end of record]separated by HEX 0a and MSH ).And i kno the separator between is HEX 0a.I need to change from 0a to HEX 0d 0d.
How to replace frm 0a to 0d 0d in HEX.
If there is no separator(Here HEX 0a) in between the given segments then script should promt error.:Wrong message!!!!

3)Can i make this HEX parameter ( say 0d 0d) configurable ,to store in a variable and change in the script.

4)The script should exit at that point with proper logging.

I am totally stuck with this requirment of the script.
Please help.
Oct 30 '06 #11
miller
1,089 Expert 1GB
Hello somyasager.

I'm grateful that you took my initial advice to attempt a solution before posting a problem to heart. It appears that you've put a lot of effort into the goal of this script, which is great.

Unfortunately, I (personally) cannot help you anymore with this. If it were just a bug that you needed help decoding, of course. If it were clear specifications that you needed help coming up with an attack method, then of course. But at this point it sounds like like I'm investing time into educating you concerning a problem that I cannot get a clear understanding of compounded by a language barrier.

My second script that I posted here should give you an example of how to write a perl code that will read in a file, translate text on a per line or multi line basis, and output those results back to their original file.

Given that information, all you need to learn how to do is use regular expressions or some other logic to make the transformations that you require. Unfortunately I cannot read your mind to help with you them at this point.

Anyway, I'm only bothering to respond since I've invested a couple of hours to helping you already, and I did not want you to be waiting futilly for another response.

...

I've attempted to quickly answer your lateast questions, but I'm still confused by what you want. To answer your basic question, yes, I'm certain that whatever you're attempting to do is possible. Basically you need to use regular expressions to detect when you want to attempt a search and replace, and regular expressions to do the actually search and replace. Also, I'm pretty sure that you mean hex sequence and not hex characters, but once again, I don't know.

Anyway, good luck in your quest.
Oct 30 '06 #12
Hi ,

I am writing a script that changes the Hex Sequence in a given file:
The code is as follows:
################################################## ###########

#!/usr/bin/perl -w

#Perl script to change the HEX sequence from a given value to new value.
#Here "0a" in replaced by "0a 0b"

package FooterHeader;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(
sub FHSBHS($)
);


sub FHSBHS ($)
{


my $fileName= shift;
open(FILEREAD, "< $fileName");
$FILE = "$fileName";
open(FILE) or die("Could not open file.");
foreach $line (<FILE>)
{
my $hex = unpack( 'H*', $line );
my $segsep = "0a";
my $recsep ="0a 0b";
$hex =~ s/$segsep/$recsep /gi ;
print "$hex\n";
open(OUTPUT, "> $fileName") or die "Can't open output file $fileName\n";
print OUTPUT $hex;
close OUTPUT;
print "\n";
}
close FILEREAD;
}

#calling the above function with one command line parameter i.e filename.
FHSBHS($ARGV[0]);
################################################## ###########
I am having few problems with this script.
1.File is changed to hex format and the sequence seemed change but not able to convert back to ASCII.File is written in the same HEX format.

please help how it can be written back to the ASCII format with the changed HEX sequence .
Nov 2 '06 #13
miller
1,089 Expert 1GB
Hi my partner in crime somyasager. Here is your latest script attempt with comments added at lines you should think about. Your script is currently full of logic errors, so read my comments and maybe you'll learn something.

Expand|Select|Wrap|Line Numbers
  1. #!/usr/bin/perl -w
  2.  
  3. #Perl script to change the HEX sequence from a given value to new value.
  4. #Here "0a" in replaced by "0a 0b"
  5.  
  6. package FooterHeader;
  7.  
  8. require Exporter;
  9. our @ISA = qw(Exporter);
  10. #ERROR: read up on Exporter.  This statement exports a sub named "sub", and something else I can't even guess at.  Only include the explicit function name in your export. ie: our @EXPORT = qw(FHSBHS);
  11. our @EXPORT = qw(
  12. sub FHSBHS($)
  13. );
  14.  
  15. #WARNING: Add "use strict;" here.  It will help you avoid any errors.
  16.  
  17. sub FHSBHS ($)
  18. {
  19.     my $fileName= shift;
  20.     open(FILEREAD, "< $fileName");
  21. #WARNING: Why create a second input file handle here named FILE when you already have FILEREAD?  I'm guessing that this is a debugging step, but this is a bad idea.  Just use FILEREAD.
  22.     $FILE = "$fileName";
  23.     open(FILE) or die("Could not open file.");
  24.     foreach $line (<FILE>)
  25.     {
  26.         my $hex = unpack( 'H*', $line );
  27.         my $segsep = "0a";
  28. #ERROR: Do you really want a space between these two characters?  I'm guessing that your copying the formatting that you see in your hex editor.  But this will screw up the reverse operation
  29.         my $recsep ="0a 0b";
  30. #ERROR: Do you really want a space after the replaced value?  I don't think  you do.  Remove the space after $recsep.
  31.         $hex =~ s/$segsep/$recsep /gi ;
  32. #ERROR: Great.  You've done the unpacking, the search and replace, but what about repacking teh string?.  It would look something (maybe exactly) like this: $line = pack( 'H*', $hex);
  33.         print "$hex\n";
  34.  
  35. #ERROR: BAD BAD BAD.  You're attempting to open and write to a file that you are currently reading from.  This might work if you were working with fixed record length files, but you are explicitly increasing the number of characters in your line.  This will cause bad things.  You need to open an output stream to a different file, before starting your file read loop, and then simply move the newly created file over your old file at the end of hte transformations.
  36.         open(OUTPUT, "> $fileName") or die "Can't open output file $fileName\n";
  37. #WARNING: You're going to want to be printing the $line value and not $hex in the end I think.
  38.         print OUTPUT $hex;
  39.         close OUTPUT;
  40.         print "\n";
  41.     }
  42.     close FILEREAD;
  43. }
  44.  
  45. #calling the above function with one command line parameter i.e filename.
  46. FHSBHS($ARGV[0]);
  47.  
Nov 6 '06 #14

Post your reply

Sign in to post your reply or Sign up for a free account.

Similar topics

2 posts views Thread by Bob | last post: by
58 posts views Thread by @ | last post: by
6 posts views Thread by John Smith | last post: by
77 posts views Thread by Hunn E. Balsiche | last post: by
1 post views Thread by Babu | last post: by
7 posts views Thread by Piotr Turkowski | last post: by
35 posts views Thread by lnatz | last post: by
6 posts views Thread by surfivor | last post: by
reply views Thread by zhoujie | last post: by
reply views Thread by haryvincent176 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.