From: Ben Bacarisse on
pk <pk(a)pk.invalid> writes:

> Ben Bacarisse wrote:
<snip>
>> sed -e '/^string1$/N' -e 's/^string1\nstring2$/string3\nstring4/'
>
> (nitpick)
> That has a slight issue for inputs like
>
> string1
> string1
> string2
> etc.

Ah, yes. I had a nagging feeling I was posting too fast without
thinking the corner cases out.

> so the canonical way, as per the sed FAQ is
>
> sed -e :a -e '$!N;s/^string1\nstring2$/string3\nstring4/;ta' -e 'P;D'
>
> and, since \n in the rhs isn't supported by all seds, it should then be
>
> sed -e :a -e '$!N;s/^string1\nstring2$/string3\
> string4/;ta' -e 'P;D'

However, neither of these work for me:

Script started on Thu 27 May 2010 20:20:56 BST
$ cat eg
string1
string2
xxxx
string1
string2
xxxx
$ sed -e :a -e '$!N;s/^string1\nstring2$/string3\
> string4/;ta' -e 'P;D' <eg
string3
string4
xxxx
string1
string2
xxxx

I may have got some detail wrong. I'd investigate further except I find
sed to be the closest thing to write-only code that I come across these
days. (It's old age I am sure -- I used to be fine with TECO.)

I think:

sed -e '/^string1$/N' -e 's/^string1\nstring2$/string3\nstring4/;t' -e 'P;D'

fixes the issue you pointed out, but it uses a default jump target. Is
there such a things as bad sed style? :-)

--
Ben.
From: pk on
Ben Bacarisse wrote:

>> sed -e :a -e '$!N;s/^string1\nstring2$/string3\
>> string4/;ta' -e 'P;D'
>
> However, neither of these work for me:
>
> Script started on Thu 27 May 2010 20:20:56 BST
> $ cat eg
> string1
> string2
> xxxx
> string1
> string2
> xxxx
> $ sed -e :a -e '$!N;s/^string1\nstring2$/string3\
>> string4/;ta' -e 'P;D' <eg
> string3
> string4
> xxxx
> string1
> string2
> xxxx

Right, my bad. These should work:

$ sed '$!N;s/^string1\nstring2$/string3\
string4/' -e 'P;D' eg
string3
string4
xxxx
string3
string4
xxxx
$ sed '$!N;s/^string1\nstring2$/string3\
string4/;t' -e 'P;D' eg

Basically the jump can be removed, or it can be to the end of the script. If
the replacement does not overlap with the searched text, they are virtually
equivalent.

> I may have got some detail wrong. I'd investigate further except I find
> sed to be the closest thing to write-only code that I come across these
> days. (It's old age I am sure -- I used to be fine with TECO.)
>
> I think:
>
> sed -e '/^string1$/N' -e 's/^string1\nstring2$/string3\nstring4/;t' -e
> 'P;D'

This also works but I like it less (just personal taste).

> fixes the issue you pointed out, but it uses a default jump target. Is
> there such a things as bad sed style? :-)

Some people on this list say that using sed for anything else than simple
substitutions on the same line is bad, so we better stop it here :-)
(although in most cases I agree with that because simpler alternatives
exist)
From: Janis Papanagnou on
pk wrote:
> Ben Bacarisse wrote:
>
>>> sed -e :a -e '$!N;s/^string1\nstring2$/string3\
>>> string4/;ta' -e 'P;D'
>> However, neither of these work for me:
[...]
>
> Right, my bad. These should work:
[...]
>
>> I may have got some detail wrong. I'd investigate further [...]
[...]
>
> Some people on this list say that using sed for anything else than simple
> substitutions on the same line is bad, so we better stop it here :-)
> (although in most cases I agree with that because simpler alternatives
> exist)

That's interesting. When I read in this posting about the above mistakes
done with sed, where the application here is something that still appears
to me to be a simple substitution, I thought exactly about the suggestion
not to use sed for anything more complex than substitution _on a single
line_.

Janis
From: Ben Bacarisse on
pk <pk(a)pk.invalid> writes:
> Ben Bacarisse wrote:
<snip>
>> I think:
>>
>> sed -e '/^string1$/N' -e 's/^string1\nstring2$/string3\nstring4/;t' -e
>> 'P;D'
>
> This also works but I like it less (just personal taste).

I think it goes a bit beyond taste. You version does not need a part of
the target string to be repeated. That's clearly a Bad Thing for
maintenance but the most of my sed commands are never maintained -- I
use it mostly for one-offs.

<snip>
--
Ben.
From: Ed Morton on
On 5/28/2010 3:18 AM, pk wrote:
> Ben Bacarisse wrote:
<snip>
>> Is
>> there such a things as bad sed style? :-)
>
> Some people on this list say that using sed for anything else than simple
> substitutions on the same line is bad, so we better stop it here :-)

Maybe it's just me, but I think this thread with it's many iterations of sed
attempts:

sed -e '{
N
s/^string1\nstring2$/string3\nstring4/
}'

sed -e '/^string1$/N' -e 's/^string1\nstring2$/string3\nstring4/'

sed -e :a -e '$!N;s/^string1\nstring2$/string3\nstring4/;ta' -e 'P;D'

sed -e :a -e '$!N;s/^string1\nstring2$/string3\
string4/;ta' -e 'P;D'

sed -e '/^string1$/N' -e 's/^string1\nstring2$/string3\nstring4/;t' -e 'P;D'

sed '$!N;s/^string1\nstring2$/string3\
string4/' -e 'P;D'

each with arcane configurations of single-character commands and each attempting
to solve non-obvious problems that the others have with some input sets, pretty
well underscores the point that you shouldn't attempt to use sed to do anything
with input that spans lines.

I can't imagine coming across one of those commands and being able to tell what
it does without some long, SERIOUS thought and reference to manual pages.

The awk solution, on the other hand:

awk -v RS= '{sub(/string1\nstring2/,"string3\nstring4")}1'

is pretty clear and only took one attempt to get right.

Ed.