Note sure if this is the best approach, but I came up with the following pattern: (?:(?:^|\G(?!^)\h*,\h*)([[:alnum:]]+\b)(?=(\h*,\h*[[:alnum:]]+)*\h+([[:alnum:]]+_[[:alnum:]]+\h*$))|(\h+[[:alnum:]]+_[[:alnum:]]+\h*$\R?)), replacing it with (?{1}$1 $3\n(?{2}~~:):) and a second replace with ^~~ and replacing with an empty string.
It converts as you desired, working for an arbitrary number of commas. Here's what it does:
(?:^|\G(?!^)\h*,\h*)([[:alnum:]]+\b)(?=(\h*,\h*[[:alnum:]]+)*\h+([[:alnum:]]+_[[:alnum:]]+)\h*$)
This matches the comma separated strings (and the underscored value in a lookahead)
(?:^|\G(?!^)\h*,\h*) matches the start of the line, or the previous match followed by horizontal spaces comma horizontal spaces
([[:alnum:]]+\b) matches letters/numbers followed by a word boundary, stores into capturing group 1
(?= starts a lookahead, so we don't actually match, just assert and store into capturing groups
(\h*,\h*[[:alnum:]]+)* matches the next words, if there are any following and stores the last into capturing group 2, if there is no following word, capturing group 2 is not matched
\h+([[:alnum:]]+_[[:alnum:]]+)\h*$ matches the underscored word, captures it into group 3, there are horizontal spaces before and might be after
(\h+[[:alnum:]]+_[[:alnum:]]+\h*$\R?))
This matches the underscored word and optionally the following newline, so we can replace it with an empty string.
The replacement (?{1}$1 $3\n(?{2}~~:):) checks if the first capturing group is matched (thus one of the comma separated words). If so it inserts this word a space, the underscored word, a newline and ~~ if it's not the last one. I needed ~~ to make the \G work correctly in all cases, you could use any string that's unlikely to reappear in the content. If the first capturing group is not matched, the replacement will be empty. The second replace with ^~~ is used to finally remove it.