Jarek has asked for the wisdom of the Perl Monks concerning the following question:

Hi everyone. Let's say I've got a file which contains the same repeated parts of block of text. That block of text looks like we could say that we can create some kind of pattern from it... for example:
line something starts here { contains line 1 contains line 2 contains line 3 contains line 4 ends here } next block of something starts here { contains line 1 contains line 2 contains line 3 contains line 4 ends here }
etc. That's the file construction. Now I need to look for the string which is always in front of "{" and depends on the action I need to for example cut whole block so from start to end, modify for example line 4, or replace line 2 to something. The problem is I know how to find it in the text file but the problem is how to do something like "find this and since that delete next 4 lines and save the file". Thank you for your help. Regards, Jarek

Replies are listed 'Best First'.
Re: Replacing, cutting, deleting lines in the file
by toolic (Bishop) on Nov 23, 2009 at 17:06 UTC
    There are 3 common approaches that I can think of:
    • Read the file line-by-line and use a state variable to remember when you are inside a block of interest.
    • Read the file record-by-record by re-defining the $/ ($INPUT_RECORD_SEPARATOR) special variable.
    • Read the file record-by-record by using Range Operators.
    Try one of these out, then post code if you are still having trouble.
Re: Replacing, cutting, deleting lines in the file
by almut (Canon) on Nov 23, 2009 at 17:14 UTC
    how to do something like "find this and since that delete next 4 lines and save the file"

    Possible approaches:

    1. Use an appropriate input record separator $/ (in your case, it looks like "ends here }\n" might work) and split the file into records that you then treat individually (as if they were separate files).
    2. Use a so-called state machine, i.e. set/unset variables (depending on regex matches, for example) to represent the state that you're currently in while processing the file, such as state "line something starts here", or state "next block of something starts here", and then switch your processing of the lines accordingly.
Re: Replacing, cutting, deleting lines in the file
by JavaFan (Canon) on Nov 23, 2009 at 17:08 UTC
    Unless you're on a file system that allows for files which are sequences of lines (the only OS I know of which has such file systems and can run Perl is VMS), there are only two ways:
    1. Read the entire file into memory (for instance, into arrays), do all the slicing and dicing, and write out the result if you're done.
    2. Read in the file part by part, write it back to a different file after the slicing and dicing. When done, rename the new file to the original.
Re: Replacing, cutting, deleting lines in the file
by gulden (Monk) on Nov 23, 2009 at 19:27 UTC

    A simple code snippet

    #!/usr/bin/perl -w use strict; use warnings; use constant HANDLER => { 'line something starts here {' => sub{ return "Handler 1: do s +omethig with this data\n".shift;}, 'next block of something starts here {' => sub{ return "Handle +r 2: do somethig with this data\n".shift;}, # Other record Handlers }; # Read Records while (my $line = <DATA>){ chomp $line; next unless $line =~ /{/; my $header = $line; # READ HEADER # READ BODY $/="ends here }\n"; my $body = <DATA>; chomp $body; $/="\n"; print "Get Handler for: [$header]\n"; my $output = &{HANDLER->{"$header"}}($body); print $output if $output; } __DATA__ line something starts here { contains line 1 contains line 2 contains line 3 contains line 4 ends here } next block of something starts here { contains line 1 contains line 2 contains line 3 contains line 4 ends here }
    «A contentious debate is always associated with a lack of valid arguments.»
      Hi, Thank you for your replies. And thank you for the code :). Anyway I will use it later when mine will be bad ;P. I've prepared something like:
      my $array_position; my $file = "/home/user/file.txt"; open FILE, $file; my @file = (<FILE>); close FILE; foreach ( @file ) { if ($_ =~ /line 3/) { $array_position=$i+1; print "Position in array = ". $array_position. "\n"; } $i++; } for ($a=$array_position-1; $a<$array_position+3; $a++) { print "Postion ".$a." in the array = " .$file[$a]; } @array = @file; splice @array, 0, 'something'; print @array;
      The file.txt contains this:
      line 1 line 2 fsefse line 3 line 4 ,... line 5 line 6>
      The problem is it doesn't want to replace first element from the array to string I specified. Any ideas why ? Regards, Jarek
        Is this what you want?
        use strict; use warnings; use Data::Dumper; my @file = (<DATA>); my @array = @file; splice @array, 0, 1,'something'; print Dumper \@array; __DATA__ line 1 line 2 fsefse line 3 line 4 ,... line 5 line 6>