6 added 747 characters in body
source | link

Here's another one, courtesy @don_crissti (if slightly modified):

sed -etD -e'$q;N;/^\(...\).*\n\1/!s/\n/&&/;:D' -eP\;D

I know youlike his a lot better. He initially asked aboutme: BBedit butwhy edit out the newlines and not just edit them in? I don't evendidn't have any answer, really know what that, and was mostly ambivalent because I didn't consider it to make much of a difference.

The thing is, though, the lookahead technique used here requires a knife-edge buffer - it could report false positives if the buffer grows any larger than the most current two input lines at a time. You should haveBalancing a single line of lookahead gets to be more difficult when you're also actually inserting newlines into the very same stream you're matching and requires that you can easily distinguish between a line of input you've inserted or a line you need to read. That balance requires at least one extra test per cycle - and I get by with the /^\n/! test above.

But a very basic part of the sed onmachinery is the s///ubstitution statement's tested return, which does conditional branching in the event of success. Because his substitutions always generate an extra line the sed line cycle - which is what clears a unixtest's return -like system does not roll over when pattern space is Deleted and test still works at the top of the script. In this way don can very simply test over every insertion and reliably evaluate the result of the previous iteration at the top of the next.

So go upvote one of his answers, thoughcause I guess he isn't going to put it here.

 

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The s/^\(\(...\).*\)\n\2/\1\2/ substitution matches the first three characters in pattern space against the the same three characters as back-referenced in \2 immediately following a \newline and afterward replaces the match with everything but one of the intervening newlines. And so the newline added with Get is squeezed away between groups.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.

I know you asked about BBedit but I don't even really know what that is. You should have a sed on a unix-like system, though.

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The s/^\(\(...\).*\)\n\2/\1\2/ substitution matches the first three characters in pattern space against the the same three characters as back-referenced in \2 immediately following a \newline and afterward replaces the match with everything but one of the intervening newlines. And so the newline added with Get is squeezed away between groups.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.


Here's another one, courtesy @don_crissti (if slightly modified):

sed -etD -e'$q;N;/^\(...\).*\n\1/!s/\n/&&/;:D' -eP\;D

I like his a lot better. He initially asked me: why edit out the newlines and not just edit them in? I didn't have any answer, really, and was mostly ambivalent because I didn't consider it to make much of a difference.

The thing is, though, the lookahead technique used here requires a knife-edge buffer - it could report false positives if the buffer grows any larger than the most current two input lines at a time. Balancing a single line of lookahead gets to be more difficult when you're also actually inserting newlines into the very same stream you're matching and requires that you can easily distinguish between a line of input you've inserted or a line you need to read. That balance requires at least one extra test per cycle - and I get by with the /^\n/! test above.

But a very basic part of the sed machinery is the s///ubstitution statement's tested return, which does conditional branching in the event of success. Because his substitutions always generate an extra line the sed line cycle - which is what clears a test's return - does not roll over when pattern space is Deleted and test still works at the top of the script. In this way don can very simply test over every insertion and reliably evaluate the result of the previous iteration at the top of the next.

So go upvote one of his answers, cause I guess he isn't going to put it here.

 

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

5 added 6 characters in body
source | link

Since you can match the dups, then you'll want to negate your action. You could do like:

sed -e'/^\n/!{$n;G;N;$n;G;N;s/^\(\(...\).*\n\1/s/\n*\)\n\2/\1\2/;}' -eP\;D <in >out

In other words start with a double spaced file, and prune out the second space between your groups.

Running that against your example input prints:

jan   ford
jan   trillian

mar   trillian

sep   marvin

Which actually leads me to a question for you: I think I get how Trillian might have two birthdays with the parallel universes and all, but could you explain why you think Marvin might have one at all? I guess September would fit, though - it's always gloomy.

I know you asked about BBedit but I don't even really know what that is. You should have a sed on a unix-like system, though.

The Get command appends sed's hold space to pattern space following an inserted \newline delimiter. The hold space is never used here, though, and so all that is Got is the \newline.

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The s/^\(\(...\).*\n\1*\)\n\2/\1\2/ patternsubstitution matches the first three characters in pattern space against the the same three characters as back-referenced in \1\2 backreference immediately following a \newline and afterward replaces the match with everything but one of the intervening newlines. If successful,And so the dependentnewline added with s///Gubstitution substituteset is squeezed away one of your patern space's newlines, and it only happens when the first three chars on one line match the first three chars on the nextbetween groups.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.

Since you can match the dups, then you'll want to negate your action. You could do like:

sed -e'/^\n/!{$n;G;N;/^\(...\).*\n\1/s/\n//;}' -eP\;D <in >out

In other words start with a double spaced file, and prune out the second space between your groups.

Running that against your example input prints:

jan   ford
jan   trillian

mar   trillian

sep   marvin

Which actually leads me to a question for you: I think I get how Trillian might have two birthdays with the parallel universes and all, but could you explain why you think Marvin might have one at all? I guess September would fit, though - it's always gloomy.

I know you asked about BBedit but I don't even really know what that is. You should have a sed on a unix-like system, though.

The Get command appends sed's hold space to pattern space following an inserted \newline delimiter. The hold space is never used here, though, and so all that is Got is the \newline.

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The /^\(...\).*\n\1/ pattern matches the first three characters in pattern space against the \1 backreference immediately following a \newline. If successful, the dependent s///ubstitution substitutes away one of your patern space's newlines, and it only happens when the first three chars on one line match the first three chars on the next.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.

Since you can match the dups, then you'll want to negate your action. You could do like:

sed -e'/^\n/!{$n;G;N;s/^\(\(...\).*\)\n\2/\1\2/;}' -eP\;D <in >out

In other words start with a double spaced file, and prune out the second space between your groups.

Running that against your example input prints:

jan   ford
jan   trillian

mar   trillian

sep   marvin

Which actually leads me to a question for you: I think I get how Trillian might have two birthdays with the parallel universes and all, but could you explain why you think Marvin might have one at all? I guess September would fit, though - it's always gloomy.

I know you asked about BBedit but I don't even really know what that is. You should have a sed on a unix-like system, though.

The Get command appends sed's hold space to pattern space following an inserted \newline delimiter. The hold space is never used here, though, and so all that is Got is the \newline.

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The s/^\(\(...\).*\)\n\2/\1\2/ substitution matches the first three characters in pattern space against the the same three characters as back-referenced in \2 immediately following a \newline and afterward replaces the match with everything but one of the intervening newlines. And so the newline added with Get is squeezed away between groups.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.

4 added 263 characters in body
source | link

Since you can match the dups, then you'll want to negate your action. You could do like:

sed -e'/^\n/!{$n;G;N;/^\(...\).*\n\1/s/\n//;}' -eP\;D <in >out

In other words start with a double spaced file, and prune out the second space between your groups.

Running that against your example input prints:

jan   ford
jan   trillian

mar   trillian

sep   marvin

Which actually leads me to a question for you: I think I get how Trillian might have two birthdays with the parallel universes and all, but could you explain why you think Marvin might have one at all? I guess September would fit, though - it's always gloomy.

I know you asked about BBedit but I don't even really know what that is. You should have a sed on a unix-like system, though.

The Get command appends sed's hold space to pattern space following an inserted \newline delimiter. The hold space is never used here, though, and so all that is Got is the \newline.

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The /^\(...\).*\n\1/ pattern matches the first three characters in pattern space against the \1 backreference immediately following a \newline. If successful, the dependent s///ubstitution substitutes away one of your patern space's newlines, and it only happens when the first three chars on one line match the first three chars on the next.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.

Since you can match the dups, then you'll want to negate your action. You could do like:

sed -e'/^\n/!{$n;G;N;/^\(...\).*\n\1/s/\n//;}' -eP\;D <in >out

In other words start with a double spaced file, and prune out the second space between your groups.

Running that against your example input prints:

jan   ford
jan   trillian

mar   trillian

sep   marvin

I know you asked about BBedit but I don't even really know what that is. You should have a sed on a unix-like system, though.

The Get command appends sed's hold space to pattern space following an inserted \newline delimiter. The hold space is never used here, though, and so all that is Got is the \newline.

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The /^\(...\).*\n\1/ pattern matches the first three characters in pattern space against the \1 backreference immediately following a \newline. If successful, the dependent s///ubstitution substitutes away one of your patern space's newlines, and it only happens when the first three chars on one line match the first three chars on the next.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.

Since you can match the dups, then you'll want to negate your action. You could do like:

sed -e'/^\n/!{$n;G;N;/^\(...\).*\n\1/s/\n//;}' -eP\;D <in >out

In other words start with a double spaced file, and prune out the second space between your groups.

Running that against your example input prints:

jan   ford
jan   trillian

mar   trillian

sep   marvin

Which actually leads me to a question for you: I think I get how Trillian might have two birthdays with the parallel universes and all, but could you explain why you think Marvin might have one at all? I guess September would fit, though - it's always gloomy.

I know you asked about BBedit but I don't even really know what that is. You should have a sed on a unix-like system, though.

The Get command appends sed's hold space to pattern space following an inserted \newline delimiter. The hold space is never used here, though, and so all that is Got is the \newline.

The Next command appends the Next input line to pattern space following an inserted \newline delimiter. Doing Get then Next for each input line gets two \newlines per input line.

The /^\(...\).*\n\1/ pattern matches the first three characters in pattern space against the \1 backreference immediately following a \newline. If successful, the dependent s///ubstitution substitutes away one of your patern space's newlines, and it only happens when the first three chars on one line match the first three chars on the next.

If it doesn't happen then when sed Prints only up to the first \newline delimiter and Deletes same it will miss the extra \newline, which will wind up at the head of the next cycle's pattern space, and so you should not try to edit a pattern space that begins with a \newline character - because those are the ones you're trying to insert.

3 added 1086 characters in body
source | link
2 added 327 characters in body
source | link
1
source | link