[SOLVED] SED Multiline edit -- Quit After First Match/Edit
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I found this nice multi-line insert command structure using SED and it works perfect except my "unique line" occurs more than once in the target file. I need to insert text only once before the first occurrence of that "unique line":
Code:
sed -e '/^unique line/ i \
First line of text to insert before unique line.\
Second line of text to insert before unique line.\
Third line of text to insert before unique line.
' -i /path/file 1>/dev/null 2>&1
I have tried inserting the SED 'q' command into the code structure using every possible method I can image but cannot get SED to quit after the first edit. Am I just barking up the wrong tree thinking 'q' can be used in this manner? Any ideas?
Further details to the above using this sample /path/file:
Code:
right shoe
foo
left shoe
foo
makes a pair
This is what the sample code above gives me if my "unique line" is "foo":
Code:
right shoe
First line of text to insert before unique line.
Second line of text to insert before unique line.
Third line of text to insert before unique line.
foo
left shoe
First line of text to insert before unique line.
Second line of text to insert before unique line.
Third line of text to insert before unique line.
foo
makes a pair
And this is what I want:
Code:
right shoe
First line of text to insert before unique line.
Second line of text to insert before unique line.
Third line of text to insert before unique line.
foo
left shoe
foo
makes a pair
bash-4.3$ cat in4.txt
right shoe
foo
left shoe
foo
makes a pair
bash-4.3$ sed '1,/^foo/ s/foo/First line of text to insert before unique line.\nSecond line of text to insert before unique line.\nThird line of text to insert before unique line.\n&/' in4.txt
right shoe
First line of text to insert before unique line.
Second line of text to insert before unique line.
Third line of text to insert before unique line.
foo
left shoe
foo
makes a pair
Last edited by allend; 06-08-2014 at 10:26 AM.
Reason: Use ampersand instead.
Hi allend and thanks for your reply... but that's cheating ... telling SED where to begin the search.
Ok, not cheating. Technically you solved the question as I presented it. What I failed to mention is the "unique line" might appear anywhere in the source file, so the /path/file could look like this:
Code:
some text
right shoe
foo
left shoe
foo
makes a pair
or it could look like this:
Code:
some text
some other text
more text
right shoe
foo
left shoe
foo
makes a pair
The only thing I can be sure about, I want to insert my lines before the first "foo" line, there will always be more than one "foo" line and I never know where the first "foo" line will appear.
An address range can be specified by specifying two addresses
separated by a comma (`,'). An address range matches lines starting
from where the first address matches, and continues until the second
address matches (inclusively).
If the second address is a REGEXP, then checking for the ending
match will start with the line _following_ the line which matched the
first address: a range will always span at least two lines (except of
course if the input stream ends).
Ok, new problem with this new SED line. I was trying to keep my post simple and clear as possible but now its coming back to bite me. The original SED command structure did not have a problem with special characters so for example, this would work fine:
Code:
sed -e '/^unique line/ i \
#First line of text to insert before unique line.\
Second/line/of/text/to/insert before unique line.\
Third line of text to; insert before unique line.
' -i /path/file 1>/dev/null 2>&1
Except of course the original problem, it would insert in front of every instance of the "unique line".
Perhaps change the delimiter for the substitute command.
Code:
bash-4.3$ sed '1,/^foo/ s:foo:#First line of text to insert before unique line.\nSecond/line/of/text/to/insert/before/unique/line.\nThird line of text to; insert before unique line.\n&:' in4.txt
right shoe
#First line of text to insert before unique line.
Second/line/of/text/to/insert/before/unique/line.
Third line of text to; insert before unique line.
foo
left shoe
foo
makes a pair
Perhaps change the delimiter for the substitute command.
That worked except (again) I failed to mention the text would also include the colon, so I changed your colon to a percent and it works like a charm. You are "genius"! Many many thanks for sticking it out with me!!
The final and *working* solution:
Code:
sed '1,/^foo/ s%foo%#First line of text to insert before unique line.\nSecond/line/of/text/to/insert/before/unique/line.\nThird line of text to; insert before unique line.\n&%' in4.txt
I tried substituting the delimiter previously but did not realize the "sed '1,/^foo/ " portion of the command line was a completely separate component unrelated to the "sed 's/word/otherword/' component, so I changed *all* forward slash to percent across the entire command line (except in the 3 lines of text) and of course it failed. Pheew! If I can figure out what that "sed '1,/^foo/ " portion is all about, why we are able to get two completely separate sed components into a single sed command line, and what the '1, is doing exactly then I will have actually learned something here. This "sed" stuff is like playing chess to me. I suck at chess. My brain just doesn't seem to hold the entire image going into these depths. All that aside. Thanks again allend!!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.