#!/usr/bin/env bash # table-to-csv.sh — convert a Cloverleaf .tbl file to CSV. # # Reverses csv-to-table.sh. Skips the prologue, dflt= line, encoded= meta, # comment lines, and #-separator lines; emits "input,output" rows. # # Usage: # table-to-csv.sh [FILE] # file or stdin # table-to-csv.sh --with-header [FILE] # emit "input,output" header # table-to-csv.sh --delim ';' [FILE] # output delimiter (default ',') # table-to-csv.sh --include-meta [FILE] # also emit prologue/default rows set -o pipefail usage() { sed -n '2,12p' "$0"; exit 0; } INPUT="" WITH_HEADER=0 DELIM=',' INCLUDE_META=0 while [ $# -gt 0 ]; do case "$1" in --with-header) WITH_HEADER=1 ;; --delim) shift; DELIM="$1" ;; --include-meta) INCLUDE_META=1 ;; -h|--help) usage ;; -*) echo "table-to-csv: unknown flag: $1" >&2; exit 2 ;; *) INPUT="$1" ;; esac shift done [ -z "$INPUT" ] || [ -f "$INPUT" ] || { echo "table-to-csv: no such file: $INPUT" >&2; exit 2; } [ "$WITH_HEADER" = "1" ] && printf 'input%soutput\n' "$DELIM" awk -v D="$DELIM" -v META="$INCLUDE_META" ' function csv_escape(s, needs_q) { needs_q = (index(s, D) > 0 || index(s, "\"") > 0 || index(s, "\n") > 0) gsub(/"/, "\"\"", s) if (needs_q) return "\"" s "\"" return s } /^[[:space:]]*$/ { next } /^[[:space:]]*#/ { next } /^prologue$/ { in_prologue=1; next } /^end_prologue$/ { in_prologue=0; next } in_prologue { next } /^dflt=/ { if (META == "1") { val = $0; sub(/^dflt=/, "", val) print "__dflt__" D csv_escape(val) } next } /^encoded=/ { next } { line = $0 gsub(/^[[:space:]]+|[[:space:]]+$/, "", line) if (line == "") next if (waiting_for_output) { print csv_escape(pending_input) D csv_escape(line) pending_input = "" waiting_for_output = 0 } else { pending_input = line waiting_for_output = 1 } } ' "${INPUT:-/dev/stdin}"