1 |
-----BEGIN PGP SIGNED MESSAGE----- |
2 |
Hash: SHA1 |
3 |
|
4 |
Rafael Barreto wrote: |
5 |
|
6 |
> Other thing... Why was necessary to ^CLOCK= before |
7 |
s/^\(CLOCK=".*"\).*$/\1/p? And which the necessity of the ( ) between |
8 |
the regular expression? |
9 |
> |
10 |
> Thanks again |
11 |
> |
12 |
|
13 |
Sorry for things being out of order, but you top-posted. The answer |
14 |
to your first question is below. |
15 |
|
16 |
The /^CLOCK=/ is NOT necessary, in this instance, and may actually |
17 |
cause problems if you're not 100% sure of your regular expression. It |
18 |
is there, simply because I was expanding your original pattern. What |
19 |
this does, though, is it tells sed to match the line with the regular |
20 |
expression before making any substitutions and/or replacements. Say |
21 |
for example, you had 2 lines in the same file with different values |
22 |
but similar structure, and you only wanted to change one of them. |
23 |
Let's go with the example you used. Let's assume that our example |
24 |
file looks something like this: |
25 |
|
26 |
# This is a comment |
27 |
CLOCK="foo1" |
28 |
# This is another comment |
29 |
TIMEZONE="GMT" |
30 |
# This is yet another comment |
31 |
CLOCK="${CLOCK}foo2" |
32 |
|
33 |
So, let's say that you wanted to change the second instance. The |
34 |
/^CLOCK=/ tells sed to ignore all lines that do NOT begin with |
35 |
'CLOCK='. So the comments ( # This is a comment ) and the 'TIMEZONE' |
36 |
directive will be ignored. Actions will only be taken on the lines: |
37 |
|
38 |
CLOCK="foo1" |
39 |
CLOCK="${CLOCK}foo2" |
40 |
|
41 |
...because they match the expression we gave sed as an "address" ( |
42 |
/^CLOCK=/ ). We would furthur specify how to change that line by our |
43 |
search and replace command (as described below): |
44 |
|
45 |
s/^\(CLOCK=\"\)\${.*}\(\".*\)$/\1foo3\2/ |
46 |
|
47 |
|
48 |
|
49 |
It is important to note here that the left and right brace characters |
50 |
( { } ) are not escaped. If they were, they would have been handled |
51 |
as metacharacters, which produces a drastically different result. |
52 |
|
53 |
If you really want to get to know sed (and awk), I HIGHLY recommend |
54 |
getting the 2 O'reilley books: Sed & Awk, and Mastering Regular |
55 |
Expressions. Both of these two books have taught me almost everything |
56 |
I know on the matter, and I refer to them frequently. |
57 |
|
58 |
HTH |
59 |
|
60 |
|
61 |
> 2005/11/7, Rafael Barreto <rafaelmbarreto@×××××.com |
62 |
<mailto:rafaelmbarreto@×××××.com>>: |
63 |
> |
64 |
> For that I understood, this command will return the line of CLOCK= in |
65 |
/etc/conf.f/clock without any comments. Is this right? Well, what I |
66 |
really want is replace just CLOCK="fool1" by CLOCK="fool2" keeping the |
67 |
comments in line. |
68 |
> |
69 |
> By the way, \1 do really what? If i put \0 the result is the entire |
70 |
line. So, could you explain me this a little more? Thanks... |
71 |
> |
72 |
> 2005/11/7, gentuxx < gentuxx@×××××.com <mailto:gentuxx@×××××.com>>: |
73 |
> |
74 |
|
75 |
I will try to answer both of your questions with this one email. |
76 |
|
77 |
The '\1' takes the first element, or element group, captured by the |
78 |
parentheses metacharacters ( \( \) ) and uses it as a variable. The |
79 |
variable '\0', as you found out, represents the entire contents of the |
80 |
"pattern space" or basically, the entire line since you're matching |
81 |
beginning ( ^ ) to end ( $ ). The variable '\0' is also synonymous |
82 |
with the ampersand metacharacter ( & ). So, if you want to change the |
83 |
value of the "CLOCK" variable in /etc/conf.d/clock, while leaving any |
84 |
comments intact, you could do something like this: |
85 |
|
86 |
sed 's/^\(CLOCK=\"\).*\(\".*\)$/\1foo2\2/' /etc/conf.d/clock |
87 |
|
88 |
This matches and captures the contents of the first set of |
89 |
parentheses, and places it into a variable accessible by '\1'. Then |
90 |
it matches 0 or more of any character type, until it matches a literal |
91 |
double-quote ( \" ). Then it matches and captures the contents of the |
92 |
second set of parentheses, and places it into a variable accessible by |
93 |
'\2'. So, to change the value, you would issue a substitution command |
94 |
( s/// ) which matches the first set and replaces it with the second |
95 |
set. The variables '\1' and '\2' are interpolated, so the values |
96 |
captured are printed. I.e. the result should be: |
97 |
|
98 |
was: |
99 |
CLOCK="foo1" # some comments here |
100 |
|
101 |
now: |
102 |
CLOCK="foo2" # some comments here |
103 |
|
104 |
|
105 |
|
106 |
> Willie Wong wrote: |
107 |
> |
108 |
> >>On Mon, Nov 07, 2005 at 01:44:42AM -0200, Rafael Barreto wrote: |
109 |
> >> |
110 |
> >>>Hi, |
111 |
> >>> |
112 |
> >>>I'm learning about the use of the sed command and I have some |
113 |
> questions. I'm |
114 |
> >>>trying to read in /etc/conf.d/clock the CLOCK variable with: |
115 |
> >>> |
116 |
> >>>sed '/^CLOCK="*"$/p' /etc/conf.d/clock |
117 |
> >>> |
118 |
> >>>This command, in principe, must print in screen the line that |
119 |
> contains |
120 |
> >>>CLOCK= in the begin, contains anything between double quotes and |
121 |
> ends. |
122 |
> Well, |
123 |
> >>>this doesn't return anything. If I enter the above command without $, |
124 |
> all is |
125 |
> >>>ok. But, if I would like to return just that line contains |
126 |
> CLOCK="anything" |
127 |
> >>>and nothing more? For example, |
128 |
> >> |
129 |
> >> |
130 |
> >>No it doesn't. What you want is the regexp ^CLOCK=".*"$ if you want |
131 |
> >>anything (including nothing) between the double quotes, or |
132 |
> >>^CLOCK=".+"$ if you want something (excluding nothing) between the |
133 |
> >>double quotes. |
134 |
> >> |
135 |
> >>The reason that removing the trailing $ worked is that it matched the |
136 |
> >>CLOCK=" part, the * character specifies 0 or more iterates of the |
137 |
> >>previous character, which is " |
138 |
> >> |
139 |
> >>HTH |
140 |
> >> |
141 |
> >>W |
142 |
> |
143 |
> Also, as you pointed out, lines with trailing comments would not be |
144 |
> returned based on the expression (even as modified): |
145 |
> |
146 |
> sed '/^CLOCK=".*"$/p /etc/conf.d/clock |
147 |
> |
148 |
> This is because the expression, as is, does not allow for anything |
149 |
> after the last double quote ("). The following expression should |
150 |
> match the line you want, and print out ONLY the 'CLOCK="foo"': |
151 |
> |
152 |
> sed -n '/^CLOCK=/s/^\(CLOCK=".*"\).*$/\1/p /etc/conf.d/clock |
153 |
> |
154 |
> How this works is as follows (since you're trying to learn sed): |
155 |
> |
156 |
> 1) the '-n' suppresses all output except that which was changed by |
157 |
> your expression/commands. |
158 |
> 2) the first expression ( /^CLOCK=/ ) gives sed the "address" at which |
159 |
> to make the changes. |
160 |
> 3) the second expression ( s/^\(CLOCK=".*"\).*$/\1/p )tells sed what |
161 |
> to do when it reaches that address. This is better broken down into |
162 |
> smaller steps: |
163 |
> a) the first half of the substitution expression ( |
164 |
> s/^\(CLOCK=".*"\).*$/ ) tells sed to match the capital letters C |
165 |
> -L-O-C-K which start a line ( ^ ), |
166 |
> b) followed by an equals sign (=), a double-quote ("), |
167 |
> c) followed by 0 or more of any character type - except newlines |
168 |
> - ( .* ), |
169 |
> d) followed by another double-quote ("). |
170 |
> e) Then, because of the parentheses metacharacters ( \( \) ), |
171 |
> store the match in the holding space (memory). |
172 |
> f) Then match 0 or more of any character type ( .* ), ending the |
173 |
> line ( $ ). |
174 |
> g) the second half ( /\1/ ) substitutes the characters "captured" |
175 |
> in the parentheses metacharacters, for the whole line |
176 |
> h) and prints ( /p ) the result |
177 |
> |
178 |
> So, while Willie's suggestion is correct, this should give you a more |
179 |
> complete solution. |
180 |
> |
181 |
> HTH |
182 |
> |
183 |
> -- |
184 |
> gentux |
185 |
> echo "hfouvyAdpy/ofu" | perl -pe 's/(.)/chr(ord($1)-1)/ge' |
186 |
> |
187 |
> gentux's gpg fingerprint ==> 34CE 2E97 40C7 EF6E EC40 9795 2D81 924A |
188 |
> 6996 0993 |
189 |
|
190 |
|
191 |
- -- |
192 |
gentoo-user@g.o <mailto:gentoo-user@g.o> mailing list |
193 |
|
194 |
|
195 |
|
196 |
|
197 |
|
198 |
- -- |
199 |
gentux |
200 |
echo "hfouvyAdpy/ofu" | perl -pe 's/(.)/chr(ord($1)-1)/ge' |
201 |
|
202 |
gentux's gpg fingerprint ==> 34CE 2E97 40C7 EF6E EC40 9795 2D81 924A |
203 |
6996 0993 |
204 |
-----BEGIN PGP SIGNATURE----- |
205 |
Version: GnuPG v1.4.1 (GNU/Linux) |
206 |
|
207 |
iD8DBQFDbvZBLYGSSmmWCZMRAu2TAJ9QluvFRh2Hvu2T1p6DxOkhsD+gUgCgvYjC |
208 |
qQ12BqJsAQHxMEfBkLTodAw= |
209 |
=LvhF |
210 |
-----END PGP SIGNATURE----- |
211 |
|
212 |
-- |
213 |
gentoo-user@g.o mailing list |