Click here to Skip to main content
15,884,799 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi,

I am trying to search for a line in a file, comment that line using a " * " and finally append the range of corresponding lines extracted from the same file. The corresponding extracted range of lines maybe present before or after the line (which is to be commented).

Below is my file Test.txt
Data to be ignored
Data to be ignored

PERFORM P5X98A-PGM-INITS. # This line needs to be commented with a *
#Append a copy of the corresponding extracted range of lines here.
Data to be ignored
Data to be ignored

P5X98A-PGM-INITS SECTION.  # Range to be extracted
data to be stored 1        # Range to be extracted
data to be stored 1        # Range to be extracted
P5X98A-PGM-INITS-EXIT. EXIT. # Range to be extracted

P5X98A-ABC-LIMIT SECTION.
Data to be stored 2
Data to be stored 2
P5X98A-ABC-LIMIT-EXIT. EXIT

Data to be ignored
Data to be ignored

PERFORM P5X98A-ABC-LIMIT.  # This line needs to be commented with a *
#Append a copy of the corresponding extracted range of lines here.
Data to be ignored
Data to be ignored


Below is my code.
<pre lang="Perl">
my $j=0;
open FILE1, "+<Test.txt" or die "Cannot open Test.txt!";

while (<FILE1>) {
	
  if (/$secarr[$j]/../$exarr[$j]/) {
   

    next if /$secarr[$j]/ || /$exarr[$j]/;
    
    if(my $dummy =~  s/^$perform[$j]/* $perform[$j]/)
   {
   	print FILE1 $_;
   }	 
     
  }
 $j++;
}


Where @secarr & @exarr contains the start and end strings. And @perform array contains all the lines starting with PERFORM statements

Thanks in advance,
Faez
Posted
Updated 5-Aug-12 18:25pm
v5

1 solution

You're talking about in-place editing, for which Perl has a special idiom: the -i command line switch (for one-liners) or the $^I special variable for larger programs. This is a lot easier and safer than using read-write mode for text files. Since you didn't provide all the config information you are using, and you weren't too clear on all you want to happen to the subject file, I'm offering this simplified code to get you on the right track:
PERL
$^I = '~'; # do in-place editing and use ~ for backup file
push @ARGV, 'Test.txt';
 
while (<>) {
    # do all your editing here
    s/^(PERFORM)/* $1/;

    # put results in output: 
    # this includes the default $_ line you edited, 
    # but can also include other stuff you want to insert
    print;
}


See for details: open and look for the -i switch in Command-Switches

If what you want to do is a lot more complex, you may want to handle the files yourself rather than with $^I, however you will still be better off opening input and output separately I think. Text is not easy to handle in rw mode.
 
Share this answer
 
v2
Comments
Faez Shingeri 9-Aug-12 6:22am    
That was an insightful article! :) Helped alot..
But my main challenge is extracting & replacing/appending the PERFORM lines with the corresponding range of lines..(Maybe into another file also).
I am able to extract only a few ranges bcoz other few ranges are within other ranges... Hence I need to repetitively parse the file, which I am unable to.. :(
Uilleam 9-Aug-12 10:16am    
I'm still not entirely clear on your task. In your example do you mean to say that the segment you labelled as "range to be extracted" which is delimited by lines of "P5X98A-PGM-INITS" is to be removed from its existing location, then inserted after the line "PERFORM P5X98A-ABC-LIMIT." (which itself should be commented out by an asterisk? Can you generalize this something like "any chunk of lines surrounded by matching PGM lines should be moved to follow the matching ABC lines (which may appear earlier or later)?

If so, I can see the temptation to do this in a rw mode as that is essentially how you would do it manually in an editor. However a better approach to me would be to do two passes:
-first extract all the PGM lines and their associated blocks of text, as well as all the ABC lines, and store it in a couple of hashes for easy reference
-second sort through all that material and write it out in the desired order in an output file. I'd walk through the list of ABC lines and then seek the matching PGM lines and data block, write the lot out, then go on to the next ABC line you found.

Does that make sense? Bear in mind that I don't know why you're doing all this so I may not know enough to give useful advice.

good luck!
Faez Shingeri 10-Aug-12 0:11am    
My apologies to have confused you on this.

The first query u have asked is exactly what I want. expect for the removal of the range. Infact, I am looking for copying the range to the line after its corresponding PERFORM statement is found.

The answer to your second query is that, "PGM" cannot be generalized since the entire string which comes after PERFORM and before SECTION is a function name. (Its a COBOL code :) )


What I have done so far ? :
1) Parsed the entire COBOL file and extracted all the lines starting with PERFORM and stored in another file.(which is around 100).
After which I have extracted all the function names and stored it in array by appending SECTION to it.
For eg: $ secarr[0] = P5X98A-PGM-INITS SECTION.
$ secarr[1] = P5X98A-ABC-LIMIT SECTION. and so on
On similar lines I have stored,
$exarr[0] = P5X98A-PGM-INITS-EXIT. EXIT.
$exarr[1] = P5X98A-ABC-LIMIT-EXIT. EXIT. and so on.

Doing this, will help me in getting lines from the starting and end ranges of respective function.

2) Next using the flip-flop operator code, I am able to print the ranges of functions into another file delimited by "\n\n", which I think will help me in storing earch ranges of lines into an array,
Eg $rangearr[0] =P5X98A-PGM-INITS SECTION.
data to be stored 1
data to be stored 1
P5X98A-PGM-INITS-EXIT. EXIT. and so on.


What I am unable to do ?

1) Unable to extract the $rangearr[3], because this range exist before $rangearr[2] in the file and hence the output file prints till $rangearr[2].
For which I need to keep on parsing the file till $rangearr[100] is met.

2) Append this ranges to its corresponding PERFORM statements. I was able to comment them beautifully with the in-line commands though :)


Now I have the flexibility to get the final output into another file "Final.txt" so that I can avoid the rw file operations repeatedly :)


Do let me know if you have any queries. And thank you for your time, patience and suggestions.


Cheers,

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900