grep exact match two parts of a string

The .* in the middle is matching everything, i.e. the purple:"grape" part. Instead (assuming you want to stick with GNU grep), I'd match each part separately with the (foo|bar) "OR" construct.

grep -oP '(red|yellow):\"[^\"]*"'

N.B. I had to add the closing ". Also, you don't need to escape the ", so you can use

grep -oP '(red|yellow):"[^"]*"'

In any case, this gives you

red:"apple"
yellow:"banana"

then to join the lines with space between them,

grep -oP '(red|yellow):"[^"]*"' | paste -sd ' ' -

Honestly, I'd naturally use sed instead.

sed -n 's/.*\(red:"[^"]*"\).*\(yellow:"[^"]*"\).*/\1 \2/p'

grep does not normally extract content off lines. It prints the lines that match a regular expression (globally, it's named after the g/re/p ed command).

Some implementations like GNU grep which you seem to be using have a -o to do some of that as an extension however.

pcregrep goes even further. Its -o can take an optional numerical argument to output the content of a capture group as opposed to the whole matched portion of the line.

pcregrep -o1 -o2 --om-separator=' ' '(red:"[^"]*").*(yellow:"[^"]*")'

That's still limited in what it can do.

To extract information from the line and do more transformation, it's a text stream editor you'd want instead as others have shown here.