Linux - Newbie This 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.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
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.
|
|
05-30-2012, 09:31 AM
|
#1
|
LQ Newbie
Registered: May 2012
Posts: 26
Rep:
|
SED replace line after match
I have the following scenario:
Code:
$ cat file
# option1
setting=blah
# option2
#setting=blah
# option3
#setting=blah
Now I need to implement a function to a script to switch between the different options. Ie. comment out the next line after the pattern "option1" and remove the comment from the next line after "option2" to activate it. Ideally I'd need a command that would first make sure that each next line after "option[1-3]" is commented out and then remove the comment from the line after "option2".
I'm not that bad at bash, but sed and awk are giving me some headache at the moment, I hope someone can help me with this.
Last edited by r00t; 05-30-2012 at 09:35 AM.
|
|
|
05-30-2012, 09:34 AM
|
#2
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 23,247
|
for me it looks much easier to recreate this file every time you run that function
|
|
|
05-30-2012, 09:38 AM
|
#3
|
LQ Newbie
Registered: May 2012
Posts: 26
Original Poster
Rep:
|
What exactly do you mean? Of course this is just an example file, the ones I want to use this for have a _lot_ more and various content and there are plenty of them (vHosts).
|
|
|
05-30-2012, 09:46 AM
|
#4
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 23,247
|
I mean you have a template file with the full content and some keywords like THIS_IS_THE_PLACE_FOR_OPTION_1 ....
and that can be easily replaced in a single sed: s/OPT_KEYWORD_1/opt_value_1/ ...
So you do not need to take care of the generated files at all.
|
|
|
05-30-2012, 09:49 AM
|
#5
|
LQ Newbie
Registered: May 2012
Posts: 26
Original Poster
Rep:
|
Yeah well this would be possible if the content of the file would stay the same. But imagine 50+ vHost configs with different IPs and domain names, it would be a mess in this case. Also the option strings are very long and not just a few words like in my example case, so I can't just replace the whole string.
Last edited by r00t; 05-30-2012 at 09:50 AM.
|
|
|
05-30-2012, 10:01 AM
|
#6
|
LQ Guru
Registered: Sep 2009
Location: Perth
Distribution: Arch
Posts: 10,028
|
Would it not be simpler to maybe populate an array with the data and then just call the number as required, ie. index 0 is option 1 and so on?
|
|
|
05-30-2012, 10:09 AM
|
#7
|
LQ Newbie
Registered: May 2012
Posts: 26
Original Poster
Rep:
|
I think using arrays would still be messy, because the option strings are very long. Example:
Code:
# option1
setting='<html><body><script type="text/javascript" src="/enc.js"></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("$key"),b=toNumbers("$iv"),c=toNumbers("$set");document.cookie="Cookie="+toHex(slowAES.decrypt(c,2,a,b))+"; path=/";location.href="$url";</script></body></html>';
|
|
|
05-30-2012, 10:48 AM
|
#8
|
LQ Guru
Registered: May 2005
Location: boston, usa
Distribution: fedora-35
Posts: 5,326
|
[quick-and-dirty]
Code:
read option
grep $option file
grep $option -A 1 file | tail -n 1 | cut -b 2- # assuming each line in file begins wit '#'
this one is better:
Code:
awk 'BEGIN { RS = "" } /option2/ {print "\#" $2 "\n" substr($3,2)}' r00t.lst
Last edited by schneidz; 05-30-2012 at 11:04 AM.
|
|
1 members found this post helpful.
|
05-30-2012, 11:28 AM
|
#9
|
LQ Newbie
Registered: May 2012
Posts: 26
Original Poster
Rep:
|
Thank you schneidz! The awk one looks good, I will test it later.
|
|
|
05-31-2012, 02:13 AM
|
#10
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852
|
Here's a sed solution:
Code:
sed -r -e '/^# option2/ { n ; s/^#// }' -e '/^# option/ { n ; s/^#*(.)/#\1/ }' file
The first -e expression says that, if the current line matches option2, then move on to the next line and substitute away any #'s at the start of it. The second -e is then applied and works the same way, only this time ensuring that there is a # at the front of every line.
Notice that the order of the two expressions is important in this case. The second expression ignores the "option2" line only due to the n option in the first expression. it means that that line is passed up and gone before the second expression ever has a chance to see it.
|
|
1 members found this post helpful.
|
05-31-2012, 07:36 AM
|
#11
|
LQ Newbie
Registered: May 2012
Posts: 26
Original Poster
Rep:
|
Many thanks David, it seems to be exactly what I was looking for (sed with n) and your explaination is very nice.
PS: Would you mind explaining the regex of the second part "s/^#*(.)/#\1/" a little more, so I completely understand it, or do you know any good paper on sed's regex? For example I don't understand this regex "*(.)" and this one "\1". Thank you in advance!
Last edited by r00t; 05-31-2012 at 07:40 AM.
|
|
|
05-31-2012, 08:02 AM
|
#12
|
LQ Addict
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 23,247
|
^ means beginning of line
#* means any number of # (including 0 or more)
(.) dot means any character, (.) means it is grouped
/ is a delimiter, between the first two there is a search expression, after the second one there is a replace expression:
# means # itself
\1 means the first group found in the search expression - which was (.)
man sed is a good place to start with (see links also at the end)
_____________________________________
If someone helps you, or you approve of what's posted, click the "Add to Reputation" button, on the left of the post.
Happy with solution ... mark as SOLVED
(located in the "thread tools")
|
|
|
05-31-2012, 08:17 AM
|
#13
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852
|
Sure.
The left-hand side:
^ == The start of the line
#* == A hashmark, found zero or more " *" times
(.) == Any single character " .", captured in parentheses for use in the replacement
In essence, it matches all lines with and without #'s in front of them. The important thing is to capture the first non-# character.
You could replace the " *" with a question mark" ?", for zero or one times, assuming that there's always only a single #.
The right-hand side:
# == A single hashmark
\1 == The contents of the first set of parentheses in the LHS match
So it takes whatever character is captured above and adds a hashmark to it, and this replaces the entire match. If the line had a hash previously, it ends up unchanged.
Notice the use of the -r option too. backreferencing, as this is generally called, is an extended regex feature in sed.
Here are a few regular expressions tutorials:
http://mywiki.wooledge.org/RegularExpression
http://www.grymoire.com/Unix/Regular.html
http://www.regular-expressions.info/
Regular expressions come in several flavors, as supported by different tools, but it's generally in the more advanced features where they differ. The big thing to worry about in grep and sed is the difference between basic and extended regex. The grep man page has a good explanation of them.
Last edited by David the H.; 05-31-2012 at 08:25 AM.
Reason: formatting change and a small addition
|
|
1 members found this post helpful.
|
All times are GMT -5. The time now is 06:28 PM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|