0

Example

File 1 :

This Dog
This Cat
This Duck
This Horse

File 2 :

...
Animal Name
...

AniMal Type
...

AnIMal Class
...

animal Brand
...

I want to do the following:

  • add Line 1 of File 1 (This Dog) just below the 1st occurrence of "Animal" (Ignore case)
  • add line 2 of File 1 (This Cat) just below the 2nd occurrence of "Animal" (Ignore case)
  • add line 3 of File 1 (This Duck) just below the 3rd occurrence of "Animal" (Ignore case)
  • add line 4 of File 1 (This Horse) just below the 4th occurrence of "Animal" (Ignore case)
  • ...

So in general, line n of File 1 should be added just below the nth occurrence of "Animal" (Ignore case).

So, how do I achieve this using "sed" or "awk" or any command in Linux?

3

With GNU sed:

$ sed '/^animal/IR File1' File2
...
Animal Name
This Dog
...

AniMal Type
This Cat
...

AnIMal Class
This Duck
...

animal Brand
This Horse
...

where the GNU extensions are as follows:

The I modifier to regular-expression matching is a GNU extension which causes the regexp to be matched in a case-insensitive manner.

and

R filename

Queue a line of filename to be read and inserted into the output stream at the end of the current cycle, or when the next input line is read. Note that if filename cannot be read, or if its end is reached, no line is appended, without any error indication.

1

This awk solution should do the trick:

awk 'NR==FNR{a[NR]=$0;next};1;tolower($1)=="animal"{print a[++i]}' file1 file2 > file3

NR==FNR{a[NR]=$0;next} accumulates file1 data in an array, skipping to next input line to prevent processing of file2 at this stage.

1 prints each input line of file2.

tolower($1)=="animal"{print a[++i]} matches "animal" case-insensitively, and outputs the corresponding array item, pre-incrementing the array index.

0

Sed

Just append a . after the last line of file_1 to signal the ending of file_1 to sed as sed has no concept of FNR of awk, IOW, sed the POSIX variety has no way of knowing when one file ends and the next starts.

The essential idea being to store the animal names in the hold area and then when the time comes to read in the file_2 we grab each newline-separated portion of the hold & attach it to the pattern space and at the same time detach it from the hold. This attach<->detach exercise is taken only on the line that comprise the literal string animal in a case-insensitive` fashion.

sed -e '
   1{
      :file1
         N
      /\n\.$/!bfile1
      s///;h;d
   }

   /^[aA][nN][iI][mM][aA][lL]/!b

   G
   s/\n/&&/2;ta
   b

  :a
   h;s/.*\n\n//;x
   s/\n\n.*//

' file_1 file_2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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