Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I want to join multiple lines in a file based on a pattern that both lines share.

This is my example:

{101}{}{Apples}
{102}{}{Eggs}
{103}{}{Beans}
{104}...
...

{1101}{}{This is a fruit.}
{1102}{}{These things are oval.}
{1103}{}{You have to roast them.}
{1104}...
...

I want to join the lines {101}{}{Apples} and {1101}{}{This is a fruit.}

to one line {101}{}{Apples}{1101}{}{This is a fruit.} for further processing.

Same goes for the other lines.

As you can see, both lines share the number 101, but I have no idea how to pull this off. Any Ideas?

/EDIT:

I found a "workaround":

First, delete all preceding "{1" characters from group two in VISUAL BLOCK mode with C-V (or similar shortcut), then sort all lines by number with :%sort n, then join every second line with :let @q = "Jj" followed by 500@q.

This works, but leaves me with {101}{}{Apples} 101}{}{This is a fruit.}. I would then need to add the missing characters "{1" in each line, not quite what I want. Any help appreciated.

share|improve this question
    
What is the maximum number in each group? Are there any lines that would remain unmatched in either group? –  Dennis Williamson Jan 30 '11 at 21:37
    
The maximum number in each group is {219} / {1219}. No, all files would match. –  ryz Jan 30 '11 at 21:46

2 Answers 2

up vote 2 down vote accepted

Instead of deleting the {1, just do

:%sort rn /\d\d\d}/

That will do a numerical sort, but on each line it will only look at three digits followed by a }.

Also, to join the lines afterwards, I would do

:g/{\d\d\d}/j!
share|improve this answer
    
@ryz: See! I told you! @Jan: +1! –  Dennis Williamson Jan 31 '11 at 1:30
    
simply perfect! thanks. –  ryz Jan 31 '11 at 17:06

Here's a way to do it in the shell with a file:

join -j 2 \
    <(sed -n '/^{...}/{s/{/{ /;s/}/ }/;p}' inputfile) \
    <(sed -n '/^{....}/{s/{./& /;s/}/ }/;p}' inputfile) |
    sed 's/^\([^ ]*\) { }{}\({[^}]*}\) {1 }\({.*}\)$/{\1}{}\2{1\1}\3/'

It uses the first two invocations of sed to split the file based on the number of digits between the first set of curly braces and adds spaces around the last three digits ({101} becomes { 101 } and {1101} becomes {1 101 }). Then it uses those three-digit numbers as a field for the join command key on. The last sed command puts the digits back where they belong and removes the extra spaces added earlier.

A vim guru could probably do something better within vim. I could do something more straightforward than the above using AWK.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.