sed: s/// not an address?

sed: s/// not an address?

am 20.12.2007 16:08:52 von Robert Latest

Hello,

I'm kind of puzzled. I'm trying to look through a file, and when something
matches, I'd like to put a certain portion of the line in sed's hold space.

OK, here's what I want. Below is a snippet of "ps afx" output, and I need
the last SCREEN process ID before some command I'm interested in (in this
case, slrn).

----------------------------------------

5710 ? \_ SCREEN
5711 pts/17 \_ /bin/bash
5841 pts/17 \_ /bin/bash
5842 pts/17 \_ slrn

----------------------------------------

Here's my script so far:

------------
#!/bin/sh
ps afx | sed -nr "s/^ *([0-9]+) \\?.*SCREEN/\\1/h;/$1/{g;p}"
------------

But sed won't let me use the 'h' command after s///, and it says "Unknown
option to s". But why can I use, for instance, the p command but not h?

I could have written this in 30 seconds using perl, but I'm currently in a
stubborn sed phase. I don't understand all this address/command thing.

robert

Re: sed: s/// not an address?

am 20.12.2007 17:40:04 von Ed Morton

On 12/20/2007 9:08 AM, Robert Latest wrote:
> Hello,
>
> I'm kind of puzzled. I'm trying to look through a file, and when something
> matches, I'd like to put a certain portion of the line in sed's hold space.
>
> OK, here's what I want. Below is a snippet of "ps afx" output, and I need
> the last SCREEN process ID before some command I'm interested in (in this
> case, slrn).
>
> ----------------------------------------
>
> 5710 ? \_ SCREEN
> 5711 pts/17 \_ /bin/bash
> 5841 pts/17 \_ /bin/bash
> 5842 pts/17 \_ slrn
>
> ----------------------------------------
>
> Here's my script so far:
>
> ------------
> #!/bin/sh
> ps afx | sed -nr "s/^ *([0-9]+) \\?.*SCREEN/\\1/h;/$1/{g;p}"
> ------------
>
> But sed won't let me use the 'h' command after s///, and it says "Unknown
> option to s". But why can I use, for instance, the p command but not h?
>
> I could have written this in 30 seconds using perl, but I'm currently in a
> stubborn sed phase. I don't understand all this address/command thing.
>

Take a deep breath and put it behind you. Don't try to use sed for anything
other than simple substitutions. If you don't want to or aren't allowed to use
perl, use awk or ruby or.... Assuming the ps afx output is as you posted above,
the awk script would be:

ps afx | awk '$NF=="SCREEN"{p=$1} $NF=="slrn"{print p}'

See, all nice and clear and sensible....

Ed.

Re: sed: s/// not an address?

am 20.12.2007 18:05:35 von Edward Rosten

On Dec 20, 8:08 am, Robert Latest wrote:

> ps afx | sed -nr "s/^ *([0-9]+) \\?.*SCREEN/\\1/h;/$1/{g;p}"
> ------------
>
> But sed won't let me use the 'h' command after s///, and it says "Unknown
> option to s". But why can I use, for instance, the p command but not h?

The s command is of this form:

s/pattern/replacement/flags

Note the flags at the end which control the usage (for instance "g"
makes it global, so it works on all instances on the current line, not
just the first). In other words, sed thinks that your "h" command is a
flag controlling the "s" command, and "h" isn't a valid flag. Try
inserting a semicolon:

sed -nr "s/^ *([0-9]+) \\?.*SCREEN/\\1/;h;/$1/{g;p}"


> I could have written this in 30 seconds using perl, but I'm currently in a
> stubborn sed phase. I don't understand all this address/command thing.

Good for you, sed is rather fun. It's worth leaarning since it's very
useful for oneliners, etc.

-Ed

Re: sed: s/// not an address?

am 21.12.2007 10:39:54 von Robert Latest

Edward Rosten wrote:

> The s command is of this form:
>
> s/pattern/replacement/flags
>
> Note the flags at the end which control the usage (for instance "g"
> makes it global, so it works on all instances on the current line, not
> just the first). In other words, sed thinks that your "h" command is a
> flag controlling the "s" command, and "h" isn't a valid flag. Try
> inserting a semicolon:

Yes, but 'p' is allowed at that point, and 'p' is a command after all.

> sed -nr "s/^ *([0-9]+) \\?.*SCREEN/\\1/;h;/$1/{g;p}"

But if I put a ; between the address and the command, how does sed know that
that command belongs to the address?

> Good for you, sed is rather fun. It's worth leaarning since it's very
> useful for oneliners, etc.

Yes, I've grown rather fond of the "find | sed | sh" approach for large
batches of files.

robert

Re: sed: s/// not an address?

am 21.12.2007 13:55:46 von Michael Tosch

Robert Latest wrote:
> Hello,
>
> I'm kind of puzzled. I'm trying to look through a file, and when something
> matches, I'd like to put a certain portion of the line in sed's hold space.
>
> OK, here's what I want. Below is a snippet of "ps afx" output, and I need
> the last SCREEN process ID before some command I'm interested in (in this
> case, slrn).
>
> ----------------------------------------
>
> 5710 ? \_ SCREEN
> 5711 pts/17 \_ /bin/bash
> 5841 pts/17 \_ /bin/bash
> 5842 pts/17 \_ slrn
>
> ----------------------------------------
>
> Here's my script so far:
>
> ------------
> #!/bin/sh
> ps afx | sed -nr "s/^ *([0-9]+) \\?.*SCREEN/\\1/h;/$1/{g;p}"
> ------------
>
> But sed won't let me use the 'h' command after s///, and it says "Unknown
> option to s". But why can I use, for instance, the p command but not h?
>
> I could have written this in 30 seconds using perl, but I'm currently in a
> stubborn sed phase. I don't understand all this address/command thing.
>
> robert


s/regexp/replacement/h
is syntax error: h is an unknown option to the s command.

s/regexp/replacement/;h
syntax correct, but h is unconditionally run.

You maybe want

/regexp/{s/regexp/replacement/;h;}

or

!s/regexp/replacement/;tL1
h
:L1
/$1/{g;p;}

Yes, better use perl or awk here.


--
Michael Tosch @ hp : com

Re: sed: s/// not an address?

am 21.12.2007 14:12:10 von Stephane CHAZELAS

On Fri, 21 Dec 2007 13:55:46 +0100, Michael Tosch wrote:
[...]
> /regexp/{s/regexp/replacement/;h;}

or

/regexp/{s//replacement/;h;}

> or
>
> !s/regexp/replacement/;tL1

! is only run a command if the address range does *not* match.
You can't use it to negate the meaning of the "s" commands wrt
t.

> h
> :L1
> /$1/{g;p;}
[...]

Instead:

s/regexp/replacement/; t2
:1
/$1/{g;p;}
d
:2
h
b1

--
Stephane

Re: sed: s/// not an address?

am 21.12.2007 15:53:48 von Michael Tosch

Stephane Chazelas wrote:
> On Fri, 21 Dec 2007 13:55:46 +0100, Michael Tosch wrote:
> [...]
>> /regexp/{s/regexp/replacement/;h;}
>
> or
>
> /regexp/{s//replacement/;h;}
>
>> or
>>
>> !s/regexp/replacement/;tL1
>
> ! is only run a command if the address range does *not* match.
> You can't use it to negate the meaning of the "s" commands wrt
> t.
>
>> h
>> :L1
>> /$1/{g;p;}
> [...]
>
> Instead:
>
> s/regexp/replacement/; t2
> :1
> /$1/{g;p;}
> d
> :2
> h
> b1
>

Then, at least,
one should omit the d (or n) command:

s/regexp/replacement/; t1
b2
:1
h
:2
/$1/{g;p;}


--
Michael Tosch @ hp : com

Re: sed: s/// not an address?

am 24.12.2007 10:59:19 von Rakesh Sharma

Try this :

sed -ne '
/SCREEN/{
s/ .*//;h;d
}
/slrn/{g;p;}
'




On Dec 20, 8:08 pm, Robert Latest wrote:
> Hello,
>
> I'm kind of puzzled. I'm trying to look through a file, and when something
> matches, I'd like to put a certain portion of the line in sed's hold space.
>
> OK, here's what I want. Below is a snippet of "ps afx" output, and I need
> the last SCREEN process ID before some command I'm interested in (in this
> case, slrn).
>
> ----------------------------------------
>
> 5710 ? \_ SCREEN
> 5711 pts/17 \_ /bin/bash
> 5841 pts/17 \_ /bin/bash
> 5842 pts/17 \_ slrn
>
> ----------------------------------------

Re: sed: s/// not an address?

am 24.12.2007 22:40:31 von Edward Rosten

Robert Latest wrote:
> Edward Rosten wrote:
>
> > The s command is of this form:
> >
> > s/pattern/replacement/flags
> >
> > Note the flags at the end which control the usage (for instance "g"
> > makes it global, so it works on all instances on the current line, not
> > just the first). In other words, sed thinks that your "h" command is a
> > flag controlling the "s" command, and "h" isn't a valid flag. Try
> > inserting a semicolon:
>
> Yes, but 'p' is allowed at that point, and 'p' is a command after all.

Yes, but p is also a valid option to s. The fact that they have the
same name is coincidence.


> > sed -nr "s/^ *([0-9]+) \\?.*SCREEN/\\1/;h;/$1/{g;p}"
>
> But if I put a ; between the address and the command, how does sed know that
> that command belongs to the address?

It doesn't. Use /blah/{command1;etc;}

> Yes, I've grown rather fond of the "find | sed | sh" approach for large
> batches of files.

Very useful. See my programs parallel and ssh_parallel here:
http://mi.eng.cam.ac.uk/~er258/code/index.html
for use with this kind of construct.

-Ed
-
(You can't go wrong with psycho-rats.)(http://mi.eng.cam.ac.uk/~er258)

/d{def}def/f{/Times s selectfont}d/s{11}d/r{roll}d f 2/m {moveto}d -1
r 230 350 m 0 1 179{1 index show 88 rotate 4 mul 0 rmoveto}for/s 12 d
f pop 235 420 translate 0 0 moveto 1 2 scale show showpage