[Perl] Insert lines before lines.


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting [Perl] Insert lines before lines.
# 1  
Old 06-09-2009
Question [Perl] Insert lines before lines.

Hi,

New problem, or challenge as they prefer in the US.

I need to insert some lines in a file before certain other lines.
To make it more clear:

Original file:

Code:
aaaa
bbbbb
ccccc
ddddd
bbbbb
fffff
ggggg

Now I want to insert the line "NEW_NEW_NEW" when I match "fffff", but I want it to be before the 5th line with "bbbbb".
Like this:

Code:
aaaa
bbbbb
ccccc
ddddd
NEW_NEW_NEW
bbbbb
fffff
ggggg

Notice that the line with "bbbbb" is more times present, so I cannot use that as search string.
It is the last present line with "bbbbb" though, perhaps that helps.

I tried:

Code:
$file_to_update = "test.txt";
open (FILE_TO_UPDATE, "<$file_to_update");
my @lines = <FILE_TO_UPDATE>;
close (FILE_TO_UPDATE);

open (FILE_TO_UPDATE, ">$file_to_update");
for (@lines) {
  if ($_ =~ m/fffff/) {
  print FILE_TO_UPDATE "NEW_NEW_NEW";
  }
  print FILE_TO_UPDATE;
}
close (FILE_TO_UPDATE);

But then I get the wrong order:

Code:
aaaa
bbbbb
ccccc
ddddd
bbbbb
NEW_NEW_NEW
fffff
ggggg

Anyone with some ideas ?

E.J.
# 2  
Old 06-10-2009
Quote:
[...] It is the last present line with "bbbbb" though, perhaps that helps.
Code:
perl -0pe'  
  s/bbbbb(?!.*bbbbb)/NEW_NEW_NEW\n$&/s
  ' infile

# 3  
Old 06-10-2009
Quote:
Originally Posted by radoulov
Code:
perl -0pe'  
  s/bbbbb(?!.*bbbbb)/NEW_NEW_NEW\n$&/s
  ' infile

Thanks for the one-liner.
For this example it works, but you understand it is part of a bigger universe :-)
And I am having trouble incorporating it in the example code.
Not to mention that I do not understand the wizardry in your one-liner.
I understand it is a conditional substitute, but what is the $ and the & doing for example ?

But let me make the problem a bit more real life.

Here is the test.txt data file (edited for the forum).
It is a ksh script and this is how it comes after an installation.
I need to modify it and I would like to have this modification done by a script.

Code:
if [ -f $topload_inprogress ]
then
		blahlblah
		rm $inprogress
		exit 1
fi 

if [ ! -f $params ]
then
	blahlblah
	rm $inprogress
	exit 1
fi 

if(($?==1))
then 
	blahlblah
	rm $inprogress
	exit 1
fi

if [[ -f $ftp_fin ]]
then
	rm $ftp_fin
else
	blahlblah
	rm $inprogress
	exit 1
fi

files=`ls $CADATA/srcdata/$source/custom/BULK/after`
for name in $files
do
	blahlblah
done

rm $inprogress
$CAROOT/prog/ca_log_message TOPOLOGY_STAT "Finished the bulk ftp topology load of $source data source."
exit 0

I need to insert a block-text (6 lines) between last 'done' and the 'rm $inprogress'.

Can your "(?!.*bbbbb)" be of any help there ?

Greetings,

E.J.
# 4  
Old 06-10-2009
Can you use the pattern ^rm $inprogress (at the beginning of the line) as a marker?
Or perhaps its last occurrence?
Do you really need both patterns done .. rm $inprogress?
Why Perl? I suppose the task could be done with a lighter tool (e.g. sed).

Last edited by radoulov; 06-10-2009 at 12:50 PM..
# 5  
Old 06-10-2009
Quote:
Originally Posted by radoulov
Can you use the pattern ^rm $inprogress (at the beginning of the line) as a marker?
Or perhaps its last occurrence?
Do you really need both patterns done .. rm $inprogress?
Why Perl? I suppose the task could be done with a lighter tool (e.g. sed).
The file comes like this, I have no control over it.
And if I have to "prepair" it manually, then I can make the text insert manually too.
But I don't want to.

The last "rm $inprogress" is at the end of the file, so it is the last occurrence.

The text-block needs to be between the last "done" and the last "rm $inprogress", that's a given.

I use Perl, because I need to make many more modifications in other files and I need to start things, stop things, etc.
Perl is perfect for this.
This is one of the many sub-routines in the script.
In fact I need to make 2 text-block insertions in this file and the second one has this problem I described.

If necessary I could call a sed command from within Perl, right ?
But I do not see why it could not be done with Perl.
Okay, I can't, but I am not the brightest Perl programmer around Smilie
Not yet. Smilie

Now I am thinking about counting the "done"s, printing all lines including the last "done". Then print my text-block and then print the last lines.
Or perhaps read 2 lines, test the 2nd line for "Finished the bulk ftp".
Print all lines until the test is true, print my test-block and print the last lines.
Something should be possible.

E.J.
# 6  
Old 06-10-2009
Quote:
Originally Posted by ejdv
The file comes like this, I have no control over it.
And if I have to "prepair" it manually, then I can make the text insert manually too.
But I don't want to.

The last "rm $inprogress" is at the end of the file, so it is the last occurrence.

The text-block needs to be between the last "done" and the last "rm $inprogress", that's a given.
OK,
you can use something like this (you should add exception handling, of course):

Code:
#!/usr/bin/perl

use warnings;
use strict;

my ( $shellscript, $pattern ) = ( shift, 'rm \$inprogress' );

my $newcode = <<_NEWCODE_;
line1
line2
...
line6
_NEWCODE_

{
    local ( $^I, @ARGV, $/ ) = ( '', $shellscript );
    while (<>) {
        s/$pattern(?!.*$pattern)/$newcode\n$&/s;
        print;
    }
}

Quote:
I use Perl, because I need to make many more modifications in other files and I need to start things, stop things, etc.
Perl is perfect for this.
This is one of the many sub-routines in the script.
In fact I need to make 2 text-block insertions in this file and the second one has this problem I described.

If necessary I could call a sed command from within Perl, right ?
But I do not see why it could not be done with Perl.
You don't need to call sed from Perl Smilie
I'm not saying that you should not use Perl for this,
but that sed is sufficient for this task.
And yes, of course, if this is only one of the tasks and you have other code in Perl, you should do it all in Perl.
# 7  
Old 06-11-2009
Quote:
Originally Posted by radoulov
OK,
you can use something like this (you should add exception handling, of course):
Hi,

Thanks for hanging in there.
I tried your code and get this:

Code:
C:\Documents and Settings\evroom\Desktop>update.pl test.txt
Can't do inplace edit without backup at C:\Documents and Settings\evroom\Desktop\update.pl line 17.

I tried using Perl on Windows (eventually it will run on a Unix machine), perhaps it's too picky.

When using this part in my code, I get the same output as the input:

Code:
s/$pattern(?!.*$pattern)/$newcode\n$&/s;

E.J.

-----Post Update-----

This works for me:

Code:
#!/usr/bin/perl -w #-d

use warnings;
use strict;

my @lines;
my $counter1 = 0;
my $counter2 = 0;

my $newcode = "line1
line2
line3
line4
line5
line6\n
";

open ( TEXT, "<test.txt");
  @lines = <TEXT>;
close TEXT;

for (@lines) {    
  if ( $_ =~ m/rm \$inprogress/ ) { $counter1++; }
}

open ( TEXT, ">test.txt");
for (@lines) {   
  if ( $_ =~ m/rm \$inprogress/ ) { $counter2++; }
  if ( $counter2 == $counter1) { print TEXT $newcode; $counter1 = 0;}
print TEXT;
}
close TEXT;

It will not win the beauty-contest but it fits the Perl slogan "There is more than one way to do it".

E.J.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Insert text before first 'n' lines

I want to put a particular text, say, the hash '#' before each of the first n lines of a file. How can I do that? (4 Replies)
Discussion started by: hbar
4 Replies

2. Shell Programming and Scripting

Insert few lines above a match using sed, and within a perl file.

Greetings all, I am trying to match a string, and after that insert a few lines above that match. The string is "Version 1.0.0". I need to insert a few lines ONLY above the first match (there are many Version numbers in the file). The rest of the matches must be ignored. The lines I need to... (2 Replies)
Discussion started by: nagaraj s
2 Replies

3. Shell Programming and Scripting

sed - insert two lines

I have done this sed command to insert one line after a specific string is found: sed '/patternstring/ a\ new line string' file1 But how do I insert two lines? This is not possible: sed '/patternstring/ a\ new line string \a new line string 2' file1 (2 Replies)
Discussion started by: locoroco
2 Replies

4. Shell Programming and Scripting

[Perl] Split lines into array - variable line items - variable no of lines.

Hi, I have the following lines that I would like to see in an array for easy comparisons and printing: Example 1: field1,field2,field3,field4,field5 value1,value2,value3,value4,value5Example 2: field1,field3,field4,field2,field5,field6,field7... (7 Replies)
Discussion started by: ejdv
7 Replies

5. Shell Programming and Scripting

Perl XML, find matching condition and grep lines and put the lines somewhere else

Hi, my xml files looks something like this <Instance Name="New York"> <Description></Description> <Instance Name="A"> <Description></Description> <PropertyValue Key="false" Name="Building A" /> </Instance> <Instance Name="B"> ... (4 Replies)
Discussion started by: tententen
4 Replies

6. Shell Programming and Scripting

Insert between lines.

Hello...I'm here again. This is the situation I want check if exist text between two lines: Example: interface description --text to verify ip adress if not exists text between 'interface' and 'ip address' i want insert the word 'no description' interface no description --if not... (4 Replies)
Discussion started by: bobbasystem
4 Replies

7. Shell Programming and Scripting

how to insert text between lines of an existing file using perl

Hi , I need some inputs on how to open a file (file.txt) and parse the text example aaa of the file and bbb of the file and add the text zzzz once i parse (aaa and bbb) and followed by the remaining of the text as it is in the file using perl programming. Thanks in advance (3 Replies)
Discussion started by: madhul2002
3 Replies

8. Shell Programming and Scripting

Insert Title To Each Lines

I have a command that returns following, but it's missing a title for each line. YOUR FULL NAME YOUR ID YOUR EMAIL YOUR ADDRESS YOUR PHONE Now, I want to add its title to each line: Name: YOUR FULL NAME ID: YOUR ID Email: YOUR EMAIL Address: YOUR ADDRESS Phone:... (2 Replies)
Discussion started by: tqlam
2 Replies

9. Shell Programming and Scripting

Insert lines between delimiters

I'm working with a file like: somestuff somemorestuff ... someadditionalstuff STARTTAG ENDTAG someotherstuff somecoolstuff ... somefinalstuffI've got some text (either in a file or piped) to put between STARTTAG and ENDTAG. I was thinking something like grepping for the line number of... (2 Replies)
Discussion started by: BMDan
2 Replies

10. UNIX for Dummies Questions & Answers

How to count lines - ignoring blank lines and commented lines

What is the command to count lines in a files, but ignore blank lines and commented lines? I have a file with 4 sections in it, and I want each section to be counted, not including the blank lines and comments... and then totalled at the end. Here is an example of what I would like my... (6 Replies)
Discussion started by: kthatch
6 Replies
Login or Register to Ask a Question