how to remove specific lines from a file

When restoring a file in my uninstall program I need to remove the lines I added to a file during the install. In between the file can be modified by the users.

Assume file1 is as follow:

xxx str2 xxxx
.....
...The Following lines containing str* have to be removed...
xxx str1 xxxx
xxx str2 xxxxx
xxxx aaa, xxx
xxxxx str4 xxx

Result:
xxx str2 xxxx
.....
xxxx aaa, xxx

I know how to remove the line "The Following lines containing str* ...":
ln=`grep -n 'The Following lines containing' | cut -d',' -f 1`
sed $lnd file1

I also know how to remove the lines with str* in it with awk:
awk 'BEGIN { FS=";" } { if ( $2 ~ /str*/ ) { print $0 } }' file1 > outputF

However, how to do this without removing the lines with str* before the line "The Following lines containing str* have to be removed" ? (the first line in file1 for example).

Any help would be greatly appreciated!!

Note sure if this works for gnu sed only...

sed '/The Following lines/,${/str/d}' file1

hi,
Hope this one can help you.

echo input the begin row
read line
nawk -v l=$line '
{
if ($0 ~ /str/)
{
        if (NR<=l)
        print $0
}
else
print $0
}' filename

A cunning approach would be to generate a patch file at install time that would then remove the lines you added, that could be done by savinging a backup of the original and doing a diff at installation time, then deleting the backup. Then at uninstall time you apply the patch.

Ygor:
That doesn't work on my sunOS 5.10. But thanks the same.

summer_cherry:
It works perfect! -and I've learned a lot about this nawk utility today. Thanks for your help!

porter:
That was what I did- however, I wanted the installation program to be able to run as many times as the users like without the need of uninstallation in between- and every time it runs it should be as clean as the first time... I thought that'd make it all a bit more dynamic...
Thanks for the suggestion!!

Hey,

To delete a line where a pattern matches, you can use sed.

sed '/^[Mm]ango/d' file1.txt

Above command will delete all the lines which starts with the word Mango or mango.

Similarly you can search the pattern in a line, if that will be found then delete the line.

:b:

Try the following :

$ cat bluemoon.sh
awk '
/The Following lines containing [^[:space:]]*\* have to be removed/ {
   str = $0;
   sub(/.*The Following lines containing /, "", str);
   sub(/\* have to be removed.*/, "", str);
}
! str || $0 !~ str
' bluemoon.dat
$ cat bluemoon.dat
xxx string2 xxxx
.....
...The Following lines containing string* have to be removed...
xxx string1 xxxx
xxx string2 xxxxx
xxxx aaa, xxx
xxxxx string4 xxx

$ bluemoon.sh
xxx string2 xxxx
.....
str=<string>
xxxx aaa, xxx

$

Jean-Pierre.

awk 'no&&/str/{next};/The F/{no=1;next}1' filename

Thanks all for your response!!

radoulov: it doesn't seem to work on Solaris (syntax error)

aigles: is it bourne-shell? I'm still trying to get it to work on Solaris (syntax error)

Try with nawk instead of awk

Jean-Pierre.

Can we add a line which starts with the word Mango (or any partten in the middle of the line) only the line does not exist in the file already?
I can do a grep and check the existance & then use echo to append the line.... is there a one line command like the above? :wink:

Thanks in advance for your reply!!


  1. Mm ↩︎

Try...

grep -q Mango file1.txt || echo Mango >> file1.txt

Guru Ygor/aigles/radoulov/varungupta/porter/summer_cherry;-)

Thank you all for your advice. Very helpful!!

Nikki

As my home work, I tried to figure it out how it works (though I know it works) but still no luck:-( Would someone elabrate a little of the syntax for me? Many thanks in advance!

In awk, uninitialized variables ("no" in our case) have the numeric value zero, which in awk means false
therefore the following code means IF (0) AND /str/ (the current record contains the pattern "str"), which means IF FALSE AND TRUE (true for the records that contain the pattern), then skip this record (that's the meaning of the "next" statement).
FALSE AND TRUE == FALSE (it would have been true if both elements were true), so, the records that contain the pattern "str" before we set the variable no to 1 (which in awk means TRUE) are not affected, nothing happens:

no&&/str/{next}

The following code means: if the current record contains the pattern "The F", assign the value 1 to the variable no, then skip the record ("next"):

/The F/{no=1;next}

Then we need just: 1 (TRUE), in awk this means use default action,
which is print the current record (not affected/skipped! by the previous actions):

1

We can write all this also as:

awk '/The F/,0{if($0~/str/)next}1' filename

(another homework :))

Dear radoulov

Thank you so much! Now that I understand how it works, I'm actually able to add a little more to it to solve the problem I had (removing all the lines including different keywords):
nawk 'no&&/str1|str2|str3|...../{next};/The F/{no=1;next}1' filename

However, when I tried to run this line it compaint syntax error:
awk '/The F/,0{if($0~/str/)next}1' filename

I tried to fix with no luck:-(
I think I was able to recognize the second part- if there is a matching pattern(str) found in current line($0), skip it(next) otherwise print (1).
But I don't know how to interpret the first half. Please help me;-)

Bluemoon

If you are on Solaris, you have to use nawk or /usr/xpg4/bin/awk,
not the old broken /usr/bin/awk.

Right,
the first part is a range selector: start,end - from the pattern "The F" to 0 (0 is false, so to the end of the file(s)).

Thanks radoulov! And yes, it works exactly as you described on Solaris:-)