in reply to csv parsing

Using the interpretattion of your data provided by BioLion, the following snipper will provide the translation of the raw data using my favourite delimited text file parser Text::xSV:
use warnings; use strict; use Text::xSV; my $csv = Text::xSV->new(fh => *DATA); my %res; while (my $row = $csv->get_row()) { my $index = shift @$row; $res{$index}->{id} = shift @$row; push @{$res{$index}->{desc}}, shift @$row; push @{$res{$index}->{mesh}}, shift @$row; } my $xls = Text::xSV->new(); $xls->print_row($_, join(q/,/, @{$res{$_}->{desc}}), join(q/,/, @{$res +{$_}->{mesh}})) for keys %res; __DATA__ ARL6IP2,298757,Hyperalgesia,MESH:D006930 ARL6IP2,298757,Liver Diseases,MESH:D008107 ARL6IP2,298757,"Liver Failure, Acute",MESH:D017114 ARL6IP2,298757,Liver Neoplasms,MESH:D008113 CCL22,6367,Esophageal Neoplasms,MESH:D004938 CCL22,6367,Fatty Liver,MESH:D005234 CCL22,6367,Fetal Growth Retardation,MESH:D005317 CCL22,6367,Fever,MESH:D005334
$ perl tst.pl CCL22(Esophageal Neoplasms,Fatty Liver,Fetal Growth Retardation,Fever) +,(MESH:D004938,MESH:D005234,MESH:D005317,MESH:D005334) ARL6IP2(Hyperalgesia,Liver Diseases,Liver Failure, Acute,Liver Neoplas +ms),(MESH:D006930,MESH:D008107,MESH:D017114,MESH:D008113)
Since, AFAIK, the .xls format is one of many M$ proprietary formats, I would then ...
  1. Modify my $xls = Text::xSV->new(); to read my $xls = Text::xSV->new(filename => 'foo.xls.csv'); - thus facilitating the saving of the translated file
  2. Use Win32::OLE to start an Excel session to import the generated file (foo.xls.csv) and save it to the target .xls filename - it's a bit hard to demonstrate on a Linux box (yes, I have no Windoze:-)), so any amount of google hits are there provide guidance for this step.
BTW, use perldoc TextxSV to find how to change the args to the constructor in order to read from your actual file - basically it involves changing fh => *DATA to filename => path_to_file.

Update 1:

Oops, I really ought to have looked _closely_ at the results - missing delimiter between the 2 lists - now corrected

Update 2:

Having re-read your OP, I see that the brackets were merely placeholders indicating column/field limits, so bearing this in mind, I simplified the snippet (to utilise the print_row() call) and re-structure the print loop.

A user level that continues to overstate my experience :-))