LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 05-10-2010, 01:11 PM   #1
webhope
Member
 
Registered: Apr 2010
Posts: 184

Rep: Reputation: 30
sed - testing multiline search and replace


Hi, I found a example how to do multiline search and replace. I try to make this working to my needs but with no success :-(

Step 1

I make a file with few lines:
one
two
five

Now I want to change it by the code:

Code:
sed -n '1h;1!H;${;g;s/one*five/one two three four five/g;p;}' test.lst
I run it but got this result:
one
two
five

no change. Somebody help?

Original code:
Code:
sed -n '1h;1!H;${;g;s/<h2.*</h2>/No title here/g;p;}' sample.php > sample-edited.php;

Last edited by webhope; 05-10-2010 at 03:45 PM.
 
Old 05-10-2010, 01:27 PM   #2
crts
Senior Member
 
Registered: Jan 2010
Posts: 2,020

Rep: Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757
Quote:
Originally Posted by webhope View Post
Now I want to change it by the code:

Code:
sed -n '1h;1!H;${;g;s/one*five/one two three four five/g;p;}' test.lst
Hi,

I tried your code with one small change:
Code:
sed -n '1h;1!H;${;g;s/one.*five/one two three four five/g;p;}' test.lst
Notice the '.' before '*'. It worked for me.
Hope this helps.
 
Old 05-10-2010, 01:40 PM   #3
webhope
Member
 
Registered: Apr 2010
Posts: 184

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by crts View Post
I tried your code with one small change:

Notice the '.' before '*'. It worked for me.
Hope this helps.
Ooops. This was foolish. But next step. I want to use variables to get pattern there:

Step 2

Code:
clear
search="one.*five"
replace="one two three four five"
sed -n "1h;1!H;${;g;s/"$search"/"$replace"/g;p;}" /boot/grub/test.lst | head -n 4
This returns error of token near "("
How should I to correct it to have regular syntax?

Last edited by webhope; 05-10-2010 at 03:45 PM.
 
Old 05-10-2010, 02:26 PM   #4
crts
Senior Member
 
Registered: Jan 2010
Posts: 2,020

Rep: Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757
Quote:
Originally Posted by webhope View Post
Ooops. This was foolish. But next step. I want to use variables to get pattern there:

Step 2.

Code:
clear
search="one.*five"
replace="one two three four five"
sed -n "1h;1!H;${;g;s/"$search"/"$replace"/g;p;}" /boot/grub/test.lst | head -n 4
This returns error of token near "("
How should I to correct it to have regular syntax?
Try this
Code:
sed -n "1h;1! H;$ {;g;s/$search/$replace/g;p;}" /boot/grub/test.lst |head -n 4
Notice the extra space at '1! H' and '$ {'. You also just need one enclosing pair of double-quotes (" ").
 
1 members found this post helpful.
Old 05-10-2010, 02:40 PM   #5
webhope
Member
 
Registered: Apr 2010
Posts: 184

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by crts View Post
Try this
Code:
sed -n "1h;1! H;$ {;g;s/$search/$replace/g;p;}" /boot/grub/test.lst |head -n 4
Notice the extra space at '1! H' and '$ {'. You also just need one enclosing pair of double-quotes (" ").
Yeah! The extra space before H and { works! Thanx

I am gonna to try it all in loop with an array.

Here it is:

Code:
search="one.*five"
content=("one two three four five" "bla bla bla bla" "na na na na")
n=0
sed -n "1h;1! H;$ {;g;s/$block/${content[$n]}/g;p;}" /boot/grub/test.lst | head -n 4
Returns some error

Last edited by webhope; 05-10-2010 at 03:45 PM.
 
Old 05-10-2010, 03:59 PM   #6
crts
Senior Member
 
Registered: Jan 2010
Posts: 2,020

Rep: Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757
Quote:
Originally Posted by webhope View Post
Yeah! The extra space before H and { works! Thanx

I am gonna to try it all in loop with an array.

Here it is:

Code:
search="one.*five"
content=("one two three four five" "bla bla bla bla" "na na na na")
n=0
sed -n "1h;1! H;$ {;g;s/$block/${content[$n]}/g;p;}" /boot/grub/test.lst | head -n 4
Returns some error
If the error is
Code:
sed: -e expression #1, char 0: no previous regular expression
then this is because there is no variable named 'block'.
Change your code either to
Code:
search="one.*five"
content=("one two three four five" "bla bla bla bla" "na na na na")
n=0
sed -n "1h;1! H;$ {;g;s/$search/${content[$n]}/g;p;}" /boot/grub/test.lst | head -n 4
or
Code:
block="one.*five"
content=("one two three four five" "bla bla bla bla" "na na na na")
n=0
sed -n "1h;1! H;$ {;g;s/$block/${content[$n]}/g;p;}" /boot/grub/test.lst | head -n 4
 
Old 05-10-2010, 04:46 PM   #7
webhope
Member
 
Registered: Apr 2010
Posts: 184

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by crts View Post
If the error is
Code:
sed: -e expression #1, char 0: no previous regular expression
then this is because there is no variable named 'block'.
Oh, feathery. I thought that the syntax is wrong. But the original code, which I try to make working, still doesn't work. So I will show you the final part.

Code:
while [[ $n -lt ${#content[@]} ]]; do
    n=$((n+1));
    original_block=$(echo ${original_content[$n]} | awk 'BEGIN { FS="\n"; RS="";}  {b = gensub(/([\]*+/()])/, "\\\\&", "g"); print b }')
  set -x
  sed -n "1h;1! H;$ {;g;s/$original_block/${content[$n]}/g;p;}" /boot/grub/test.lst
done;
$original_content - is array with blocks of original code of menu.lst
$content - is array with blocks of code that was changed
$original_block - is one item (block) from $original_content[$n]
$content[$n] - block that was changed

This report I have:
Code:
+ sed -n '1h;1! H;$ {;g;s/title Sata Mandriva kernel \(hd0,2\)\/boot\/vmlinuz BOOT_IMAGE=linux root=(hd0,2)  resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788 initrd \(hd0,2\)\/boot\/initrd.img/title Sata Mandriva
kernel (hd0,2)/boot/vmlinuz BOOT_IMAGE=linux root=UUID=eab515e9-bc3e-4024-9f01-55fddaa0fb1c  resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788
initrd (hd0,2)/boot/initrd.img/g;p;}' /boot/grub/test.lst
sed: -e výraz č.*1, znak 258: neukončený příkaz „s“
That is 3 lines of search:
Code:
title Sata Mandriva
kernel \(hd0,2\)\/boot\/vmlinuz BOOT_IMAGE=linux root=UUID=eab515e9-bc3e-4024-9f01-55fddaa0fb1c  resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788 
initrd \(hd0,2\)\/boot\/initrd.img
And 3 lines of replacement:
Code:
title Sata Mandriva
kernel (hd0,2)/boot/vmlinuz BOOT_IMAGE=linux root=(hd0,2)  resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788
initrd (hd0,2)/boot/initrd.img/g;p;}' /boot/grub/test.lst
Code:
sed: -e expression #1, char 258: "neukončený příkaz"(not enclosed command) „s“
Do you know what is wrong with the "s" command?

Last edited by webhope; 05-10-2010 at 04:48 PM.
 
Old 05-10-2010, 08:21 PM   #8
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,006

Rep: Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191Reputation: 3191
Quote:
+ sed -n '1h;1! H;$ {;g;s/title Sata Mandriva kernel \(hd0,2\)\/boot\/vmlinuz BOOT_IMAGE=linux root=(hd0,2) resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788 initrd \(hd0,2\)\/boot\/initrd.img/title Sata Mandriva
kernel (hd0,2)/boot/vmlinuz BOOT_IMAGE=linux root=UUID=eab515e9-bc3e-4024-9f01-55fddaa0fb1c resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788
initrd (hd0,2)/boot/initrd.img/g;p;}' /boot/grub/test.lst
sed: -e výraz č.*1, znak 258: neukončený příkaz „s“
One would say that all the unescaped slashes (/) in the replacement would be the issue.
 
Old 05-11-2010, 02:38 AM   #9
webhope
Member
 
Registered: Apr 2010
Posts: 184

Original Poster
Rep: Reputation: 30
Quote:
Originally Posted by grail View Post
One would say that all the unescaped slashes (/) in the replacement would be the issue.
I have changed pattern for search only. Drom replacement do I need to escape all chars like * / \ (), or only the slashes?
 
Old 05-11-2010, 02:51 AM   #10
crts
Senior Member
 
Registered: Jan 2010
Posts: 2,020

Rep: Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757Reputation: 757
Quote:
Originally Posted by webhope View Post
I have changed pattern for search only. Drom replacement do I need to escape all chars like * / \ (), or only the slashes?
That depends. If you don't use extended regular expressions you don't have to escape the braces when they are supposed to be part of the regular expression. You don't even have to escape the slash '/' if you choose another delimiter in the substitution command, e.g.
Code:
sed -e 's@expression1@expression2@' file
 
Old 05-11-2010, 04:25 AM   #11
webhope
Member
 
Registered: Apr 2010
Posts: 184

Original Poster
Rep: Reputation: 30
Code:
sed -n '1h;1! H;$ {;g;s@title Sata Mandriva kernel \(hd0,2\)\/boot\/vmlinuz BOOT_IMAGE=linux root=UUID=eab515e9-bc3e-4024-9f01-55fddaa0fb1c  resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788 initrd \(hd0,2\)\/boot\/initrd.img@title Sata Mandriva
kernel (hd0,2)/boot/vmlinuz BOOT_IMAGE=linux root=UUID=eab515e9-bc3e-4024-9f01-55fddaa0fb1c  resume=UUID=e12487ff-6d6f-44c4-9e03-33f545b3b798 splash=silent vga=788
initrd (hd0,2)/boot/initrd.img@g;p;}' /boot/grub/test.lst
sed: -e expression n.*1, char 258: command „s“ not closed
Could be the problem here? There are two breaklines:
after "@title Sata Mandriva"
and after "splash=silent vga=788"

Last edited by webhope; 05-12-2010 at 10:13 AM.
 
Old 05-13-2010, 02:21 PM   #12
webhope
Member
 
Registered: Apr 2010
Posts: 184

Original Poster
Rep: Reputation: 30
So I found I have to escape all New line characters (as I call breakline).

I used this code to escape some characters and breaklines on Search part and Replacement part:

Code:
echo "${content[1]}" | awk '{b = gensub(/([\]*+/])/, "\\\\&", "g"); printf "%s\\n",b }'
Other words: I found that Search part and Replacement part must not have new lines characters. Because of the delimiter for was a slash: // and the search part contained slashes, there was error. Then I replaced this delimiter to ampersand @@, and sed works now.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Sed / Replace multiline, multiple instances jkmaster Programming 8 01-28-2010 09:00 AM
sed - multiline search/replace with wildcard troubles Yalla-One Programming 4 12-29-2008 12:01 PM
sed search replace tomerbd1 Linux - General 9 04-10-2008 04:31 AM
sed question for search and replace jakev383 Linux - General 8 05-05-2007 05:40 AM
sed search & replace sharathkv25 Programming 2 03-07-2007 10:16 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 11:37 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration