Es gibt noch viel mehr Möglichkeiten; die arten aber (zumindest einmalig) in Arbeit aus und verschenken kann die fertige Lösung auch (fast) keiner.
Z.B. bei uns erzeugen wir csv-files gleich direkt im IFS, und haben dazu Funktionen wie csvColChar(), csvColNum(), csvColDate() usw. gebastelt - so sind auch "perverse" csv-files möglich (mit "Vorlaufsätzen", einem letzten Satz, der sagt, wie viele Sätze es waren, usw.).
Grundprinzip: ein csvCreate erstellt die Datei und setzt Defaultwerte (Trennzeichen, usw.), die csvColxxx-Funktionen schreiben die Daten durch Trennzeichen getrennt nebeneinander in einen Ausgabepuffer und ein csvLine() schreibt den Puffer in die IFS-Datei.
Einmal Arbeit gewesen, aber nun ist es die Erstellung jedweden csv-files ein Kinderspiel.