1

Hello I am trying to use awk to merge two text files in a rather peculiar way, taking two lines from file1, a group of word(s) from file2 (but placed on a separate line), alternating ad infinitum.  Groups of word(s) from file2 are delimited by commas.  For example:

file1

A Partridge in a Pear Tree
Two Turtle Doves
Three French Hens
Four Calling Birds
Five Gold Rings
Six Geese a-Laying
Seven Swans a-Swimming
Eight Maids a-Milking
Nine Ladies Dancing
Ten Lords a-Leaping
Eleven Pipers Piping
Twelve Drummers Drumming
Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
While I nodded, nearly napping, suddenly there came a tapping,
As of some one gently rapping, rapping at my chamber door.
“’Tis some visitor,” I muttered, “tapping at my chamber door—
            Only this and nothing more.”

file2

I was born, on Mars, the red planet
I love frogs, they are so tasty, with, ketchup, I am hungry

Output file

A Partridge in a Pear Tree
Two Turtle Doves
I was born
Three French Hens
Four Calling Birds
on Mars
Five Gold Rings
Six Geese a-Laying
the red planet
Seven Swans a-Swimming
Eight Maids a-Milking
I love frogs
Nine Ladies Dancing
Ten Lords a-Leaping
they are so tasty
Eleven Pipers Piping
Twelve Drummers Drumming
with
Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
ketchup
While I nodded, nearly napping, suddenly there came a tapping,
As of some one gently rapping, rapping at my chamber door.
I am hungry
“’Tis some visitor,” I muttered, “tapping at my chamber door—
            Only this and nothing more.”

Details:

  • file1 is split into couplets of two lines, regardless of content
  • A line in file2 may have any number of groups (i.e., any number of commas)
  • A group in file2 may have any number of words (including zero???)
  • file1 and file2 may be arbitrarily long
  • Desired behavior when you reach the end of one file but still have data in the other is unspecified.

How do I do this?

closed as unclear what you're asking by Scott, Jeff Schaller, Archemar, dhag, MelBurslan Jul 20 '16 at 22:16

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • 2
    Please define (describe) your problem. Is file1 split after every two lines, based on some content of the file, pre-specified line numbers, or something else?  Is file2 split after every three words, based on the commas, based on some content of the words, or something else?  Is it guaranteed that file2 will always have exactly one line? – Scott Jul 20 '16 at 8:39
  • Thanks for fast reaction:). I asked a question inaccurately. File1 is split after every two lines pre-specified line numbers. File2 split after every three words, based on the commas. Scott asked : Is it guaranteed that file2 will always have exactly one line? Unfortunately not :(. File 1 and file2 have a random number of lines. – darik2 Jul 20 '16 at 11:09
  • (1) An example of “Insert[ing] a line at a specified line number” would be inserting a line at line 42. An example of “Insert[ing] lines at specified line numbers” would be inserting lines at lines 1, 4, 9, 17 and 42. Inserting after every two lines isn’t really an example of either of these. … (Cont’d) – Scott Jul 20 '16 at 19:25
  • (Cont’d) …  (2) My second question was whether File2 is supposed to be split after every three words or based on the commas, or something else.  By saying “File2 [is] split after every three words, based on the commas,” you give us no guidance regarding how to handle a File2 line like “The quick brown fox, jumps over, the lazy dog.”  If you are guaranteeing the File2 has a comma after every third word, you should mention that.  Although, I guess, by putting “Paris11”, “22London”, and “Berlin33” on separate lines, you’ve hinted that we should ignore word count in File2. … (Cont’d) – Scott Jul 20 '16 at 19:25
  • (Cont’d) …  (3) Your new example is inconsistent with your first one, unless there’s some more complex rule hiding in the woodwork that you’ve forgotten to mention. (“in the earth” should come after “4Ubuntu dd dddd” and “beyond the land” should come after “6Aix fff fff”.) … … … … … … … … … … … … … … … (99) Therefore, I have voted to close this question as unclear. … … … … … … … … … … … … … … … … … … … … P.S. If one (or more) of the posted answers satisfy your requirements (whatever they are), you should say so — in comments, and by “accepting” the best one. – Scott Jul 20 '16 at 19:26
1

Guessing you want to insert the sentence which are in between comma of the file2 after every 2 line of file1, you can try the following awk script:

 awk -F", *" 'NR==FNR{
                 for(i=1;i<NF+1;i++)
                    a[i]=$i
              } 
              NR>FNR{
                 print; 
                 if(FNR%2==0) 
                     print a[FNR/2]
              }' file2 file1
  • Note that it assumes file2 contains one an only one non-empty line. – Stéphane Chazelas Jul 20 '16 at 9:25
  • Could you explain how it works, step by step – darik2 Jul 23 '16 at 12:31
  • Stéphane Chazelas said: Note that it assumes file2 contains one an only one non-empty line. Is it possible to modify this code to the line in the file2 can be more? Any quantity. But always less than file1. – darik2 Jul 23 '16 at 12:52
2
awk -F ', *' '!skip {for (i = 1; i <= NF; i++) a[++n] = $i; next}
              {print}
              FNR % 2 == 0 && m++ < n {print a[m]}
             ' file2 skip=1 file1
  • 1
    Ha!  The Stack Exchange Ogre says, "This answer was flagged as low-quality because of its length and content." – G-Man Jul 20 '16 at 9:06
  • You bored with FNR==NR to use skip, didn't it? ;) – Costas Jul 20 '16 at 10:01
  • 1
    @Costas, the problem with NR==FNR is that it doesn't work correctly when the first file may be empty. – Stéphane Chazelas Jul 20 '16 at 10:22
1

Play with awk's RecordSeparator (here assuming GNU awk or recent versions of mawk)

awk '{print}!(NR%2){getline <"file2";print}' RS="\n|, " file1

If there are , in file1's line(s), a more correct version could be:

awk 'BEGIN{r=RS}{print}!(NR%2){RS=r"|, ";getline <"file2";print;RS=r}' file1

Modified question can be settled (portably) by

awk '{print};!(NR%2) && (getline <"file2")>0{gsub(", *", "\n");print}' file1
  • 1
    It's record separator. – 123 Jul 20 '16 at 10:45
1

Assuming that @oliv's interpretation is correct, this solution might also work, although it does not use awk:

paste -d '\n ' file1 <(sed  's/^/\n/;s/, */\n\n/g' file2) | sed '/^$/d'

Given the updated requirements of the OP, this no longer seems a viable approach.

  • Nice idea, but much easy cat file1 | paste -d'\n' - - <(sed 's/, /\n/g' file2) – Costas Jul 20 '16 at 9:43
  • @Costas Silly me! I forgot that paste can handle any number of files. – Michael Vehrs Jul 20 '16 at 11:06

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