ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
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.
Introduction to Linux - A Hands on Guide
This guide was created as an overview of the Linux Operating System, geared toward new users as an exploration tour and getting started guide, with exercises at the end of each chapter.
For more advanced trainees it can be a desktop reference, and a collection of the base knowledge needed to proceed with system and network administration. This book contains many real life examples derived from the author's experience as a Linux system and network administrator, trainer and consultant. They hope these examples will help you to get a better understanding of the Linux system and that you feel encouraged to try out things on your own.
Click Here to receive this Complete Guide absolutely free.
There is a much easier way to take care of the spaces no matter where they are, or if they vary from 1 instance of the file to another -- use a regex address:
Code:
sed -ri '/^\s*disable\s*=/s,yes,no,' file
Note: it may be the '-r' option, but '\s*' works for me:
Code:
$ bash --version
GNU bash, version 3.00.16(1)-release (i386-pc-linux-gnu)
$ sed --version
GNU sed version 4.1.4
YMMV
If you want to be really thorough, then maybe:
Code:
sed -ri '\#^\s*disable\s*=\s*(yes|no)\s*$#s,yes,no,' file
BTW, I did test both code lines on a dummy file on my own machine.
Analysis
The real problem is 2-part:
Find the "disable" line,
change "yes" to "no".
Once we know we have the "disable" line, the only thing in it we need to change is the "yes". Including all the allowable forms of "disable" in the replacement command is unnecessary. The regex address is exactly what's needed, why I didn't think of it 1st time 'round, I don't know. What we want/need to do is find all forms of the line that are legal in the syntax of the file. We are creating, in effect, a micro-parser for this syntax. We also do not want to change the visual alignment chosen by the author of the specific file we are working on. Splitting the line search from the word replacement does this very nicely.
In my 2nd snippet, I have again used the "any character can be the command delimiter feature, & showed the regex address equivalent, also.
I hope this isn't too much info, my excuses are: a) those who come after, & b) I'm getting ready to teach a Linux CLI class in a very few weeks.
woooow... this is really awwwwwesome archtoad6.. thanks a million its working for me...
Code:
sed -ri '/^\s*disable\s*=/s,yes,no,' file
... and please can u tell each and every option in the code how it works (i am really not familiar with sed)??? especially regex...
Thanks all for replies...
... and please can u tell each and every option in the code how it works
Here goes
Slashes in the beginning of the command are used to match lines with regexp, so: /foo/ would match all lines containing foo.
Next we do an action on the lines we match, in this case 'Substitute'.
If you want to substitute on all lines you will see something like:
sed 's/mouse/cat/' file
That would replace mouse with cat.
Archtoad6 is using comma's as separators instead of slashes, basicly you can use alot of characters, like s### s,,, s///
So now we have:
/match a line/ action on that line is S,yes,no
All lines that have foo, replace mouse with cat:
sed '/foo/s/mouse/cat/' file
Which lines do we match?
^ matches the beginning of a line.
\s is extended regexp for a space character, tabs/spaces.
* means multiple
\s* heh! Multiple space characters
So ^\s*disable\s* will match a series of space, followed by disable and a series of space. (and nothing is allowed in front of it).
Options for sed:
-r To use extended regexp, like \s
-i To edit files in place, so it will edit your file.
If you don't use -i, it will output the output to your screen instead of to the file. Always start by not using -i, look at the output. If the output is ok than use -i to edit the file.
Nice explanation, muha. Thanks. Sorry I didn't log in yesterday & answer myself.
I wish there were a short & polite form of "RTFM", perhaps "PRTMP" ("Please ... Page"), because there are many valuable man pages that bear not only reading, but re-reading. sed is one of those. I don't know how many times I have re-read that page to check some point, but I only recently realized the power (== danger, also) of the '-i' option, especially coupled w/ KWrite. I had a text file in KWrite, but there were a few things its regex Replace could not do, so I opened a Kosole & ran the necessary sed commands (w/ '-i'). When I returned to KWrite, it asked if I wanted to reload the file or ignore the change. Neat!
1 safety feature to note about sed -i: whatever you put after the 'i' becomes the suffix for the back up file, so you can easily save the original. Careful, though, the default is to make no back up.
Why I . . .
Use commas, not slashes:
"Readability" -- For me, & this is definitely personal, I find that commas make the elements of the regex stand out on the page. That allow me to more easily understand the logic "at a glance"; especially when the regex includes escaped (i.e. w/ a '\') expressions; even more so when the escaped character(s) is/are slash(es) -- e.g. "s/\/\/\//\/\//"*. I like to call these "kung fu regexes" to accuse them, in a humorous way, looking like a Chuck Norris sparring w/ David Carradine.
Normally use '-r' w/ sed:
Syntax consistency -- As explained by muha, it causes the use of "extended" regexes. This makes the syntax closer to egrep & awk. I.e. fewer minor distinctions to remember.
* BTW, "s/\/\/\//\/\//" == "s,///,//," == "s!///!//!", which is easiest to figure out?
(I added the exclamation point example because the text is punctuated w/ commas.)
aw aw aw.... damn good explanation..... thanks a lot lot muha and archtoad6,, i am sure that i couldnt have get this clarity of info in books or man pages.... thanks for sharing ur experiences....
culin, You're welcome. But also, thank you for opportunity to keep & improve my programming skills, as well as think about an interesting problem.
muha, I already said (deserved) nice things about your post #20, but I never commented on post #18. Your point about '[[:space:]]' vs. '\s' is well taken. Especially in a sed address regex, where it ('\s') obscures the 's' that is the beginning of the command. This is a classic trade off between brevity & clarity. I tend toward '\s', at least when I use it, and it's probably fine for personal 1-time stuff; but I think that in a permanent script, whether personal or public, that '[[:space:]]' might be advisable.
If this were a programming class, I could see homework questions here:
Is '[[:space:]]' exactly the same as '\s' in sed?
Is this true in:
grep,
egrep,
awk
Have the best of both worlds -- brevity when typing, clarity when reading -- write a sed script which replaces '\s' w/ '[[:space:]]' in other scripts:
in sed
in awk
in bash scripts to all lines containing:
sed,
awk,
egrep,
grep,
as appropriate.
What is the difference between '[[:space:]]' & '[[:blank:]]'?
'[[:space:]]' isn't mentioned in man regex(7), when is it valid?
2. - I did some quick tests that seem to indicate that all 3 are the same in sed, grep, egrep, & awk, when working in a single line context. (Again w/o definitive documentation, we can't be sure about '\s'.)
2. & 3c. -- Found this in "info:/grep/Regular Expressions" ("info:..." is a Konqueror ioslave):
Quote:
5.5 Basic vs Extended
=====================
In basic regular expressions the metacharacters `?', `+', `{', `|',
`(', and `)' lose their special meaning; instead use the backslashed
versions `\?', `\+', `\{', `\|', `\(', and `\)'.
Traditional `egrep' did not support the `{' metacharacter, and some `egrep' implementations support `\{' instead, so portable scripts should avoid `{' in `egrep' patterns and should use `[{]' to match a literal `{'.
GNU `egrep' attempts to support traditional usage by assuming that `{' is not special if it would be the start of an invalid interval specification. For example, the shell command `egrep '{1'' searches for the two-character string `{1' instead of reporting a syntax error in the regular expression. POSIX.2 allows this behavior as an extension, but portable scripts should avoid it.
There is similar language in the man page.
3. -- I'll leave this to a community discussion.
4. -- Well, '[[:space:]]' may not be mentioned in man regex(7), but it is in info regex at "info:/regex/Character Class Operators" (in Konqueror). There, it says:
Quote:
'space'
space, carriage return, newline, vertical tab, and form feed
Quote:
'blank'
system-dependent; for GNU, a space or tab
Now, my Q still is: where did we hear about '\s'? We know it works, but I can't quickly find it documented.
Edit: Additions & rearrangements to "Discussion", no one posted in the mean time. (Had to log out & return.)
(post 1204)
4750+ chars., a personal record -- almost double any previous
Now, my Q still is: where did we hear about '\s'? We know it works, but I can't quickly find it documented.
\s is a posix regular expression notation.
Take a look at man 1 perlre, as stated in the sed manpage
From perlre:
\s Match a whitespace character
\S Match a non-whitespace character
space \s [2]
[2] Not exactly equivalent to "\s" since the "[[:space:]]" includes also the (very rare) `vertical tabulator', "\ck", chr(11).
\s is also mentioned in the book Mastering Regular Expressions by O'reilly. It's first mention (page 42) describes it as: Generic "whitespace" with \s.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.