Combining lines based on search criteria

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Combining lines based on search criteria

Clint Harames
I have been trying to figure out the best way to combine lines based on
a specific character.
For example, if I try to combine a line ending with ',' with the line
following it...

Line 1,
Line 2,
Line 3
Line 4.

Would become:

Line 1, Line2, Line 3
Line 4.

I have tried several things, but haven't found a clean solution.  The
closest to success I have come is:
:g/,$/join
Since global first marks the lines meeting the criteria, and then
executes the command on the marked lines I though it would be the best
option.  However, each line that gets joined with a previous line
becomes unmarked.  Therefore, a line ending with comma which was joined
to a previous line is NOT reevaluated resulting in the example becoming:

Line 1, Line 2,
Line 3
Line 4.

I even tried reversing the order a global is processed by specifying a
range of $,0.  But apparently that isn't allowed (darn).

Another solution, _could_ have been to substitute the EOL character with
nothing, but vim doesn't seem to have this capability (why not??):
s/$//
or
s/\_$//
or
s/<CR>//, etc.

So far, the best thing I have come up with is:
 1. Count the number of lines ending in ',' by replacing /,$/ with /,/
2. Record key strokes into a register (a) where I manually perform a
search for a line ending with a comma, J (normal mode join), <ESC>, then
q to quit recording.
 3. Finally I execute the register {count} times (2@a in the example
above).

This works, but is kind of a sick hack, so can someone give the _right_
way to do this?
Thanks,
-Clint
Reply | Threaded
Open this post in threaded view
|

Re: Combining lines based on search criteria

Tim Chase-2
> Line 1,
> Line 2,
> Line 3
> Line 4.
>
> Would become:
>
> Line 1, Line2, Line 3
> Line 4.

Looks like

        :g/,$/.,/[^,]$/j

should do the trick for you.

That's "on each line ending in a comma, through the next line
that doesn't end in a comma, join them all together"

-tim





Reply | Threaded
Open this post in threaded view
|

RE: Combining lines based on search criteria

Keith W. Roberts
In reply to this post by Clint Harames
----Original Message----
From: Clint Harames [mailto:[hidden email]]
Sent: Thursday, October 13, 2005 2:54 PM
To: [hidden email]
Subject: Combining lines based on search criteria

> I have been trying to figure out the best way to combine
> lines based on
> a specific character.
> For example, if I try to combine a line ending with ',' with the line
> following it...
>
> Line 1,
> Line 2,
> Line 3
> Line 4.
>
> Would become:
>
> Line 1, Line2, Line 3
> Line 4.
>
> I have tried several things, but haven't found a clean solution.  The
> closest to success I have come is:
>> g/,$/join
> Since global first marks the lines meeting the criteria, and then
> executes the command on the marked lines I though it would be the best
> option.  However, each line that gets joined with a previous line
> becomes unmarked.  Therefore, a line ending with comma which
> was joined
> to a previous line is NOT reevaluated resulting in the
> example becoming:
>
> Line 1, Line 2,
> Line 3
> Line 4.
>
> I even tried reversing the order a global is processed by specifying a
> range of $,0.  But apparently that isn't allowed (darn).
>
> Another solution, _could_ have been to substitute the EOL
> character with
> nothing, but vim doesn't seem to have this capability (why not??):
> s/$// or
> s/\_$//
> or
> s/<CR>//, etc.
>
> So far, the best thing I have come up with is:
>  1. Count the number of lines ending in ',' by replacing /,$/ with /,/
> 2. Record key strokes into a register (a) where I manually perform a
> search for a line ending with a comma, J (normal mode join), <ESC>,
> then q to quit recording.
>  3. Finally I execute the register {count} times (2@a in the example
> above).
>
> This works, but is kind of a sick hack, so can someone give
> the _right_
> way to do this?
> Thanks,
> -Clint

:%s/,\s*\n/, /g

-Keith
Reply | Threaded
Open this post in threaded view
|

Re: Combining lines based on search criteria

A.J.Mechelynck
In reply to this post by Clint Harames
Clint Harames wrote:

> I have been trying to figure out the best way to combine lines based on
> a specific character.
> For example, if I try to combine a line ending with ',' with the line
> following it...
>
> Line 1,
> Line 2,
> Line 3
> Line 4.
>
> Would become:
>
> Line 1, Line2, Line 3
> Line 4.
>
> I have tried several things, but haven't found a clean solution.  The
> closest to success I have come is:
> :g/,$/join
> Since global first marks the lines meeting the criteria, and then
> executes the command on the marked lines I though it would be the best
> option.  However, each line that gets joined with a previous line
> becomes unmarked.  Therefore, a line ending with comma which was joined
> to a previous line is NOT reevaluated resulting in the example becoming:
>
> Line 1, Line 2,
> Line 3
> Line 4.
>
> I even tried reversing the order a global is processed by specifying a
> range of $,0.  But apparently that isn't allowed (darn).
>
> Another solution, _could_ have been to substitute the EOL character with
> nothing, but vim doesn't seem to have this capability (why not??):
> s/$//
> or
> s/\_$//
> or
> s/<CR>//, etc.
[...]

$ matches the (zero-length) end of the line, not the end-of-line
character that follows it. <CR> matches the four characters less-than,
C-for-Charlie, R-for-Romeo, greater-than (IIUC).

One of the idiosyncrasies of the subsitute command is that to replace a
line break by itself you must do ":s/\n/\r/" (i.e., a line break is
matched by a LF in a pattern but must be inserted as a CR in the "to"
part of a substitute).

Try

        :1,$s/,\s*\n/,/

to suppress any line break at the end of a line ending in a comma (plus
zero or more whitespace).

HTH,
Tony.