I need to parse a tab-separated CSV file using bash, examine the contents of the record, and, if the record meets certain criteria, add it to an array. Basically, I want to filter records out of a CSV file before doing something with them.
My thought was to take each row in the file, put each field into an array. I could then look at the array to see if the record meets certain conditions (e.g. field3="value", etc). If yes, I would then "reconstruct" the tab separated line and append it to a new array.
Where this seems to fail is the line where I create record
. It appears to be appending a space rather than a tab because later on, the size of details
is the same as if the record were space delimited instead of tab.
datafile=path/to/data.csv
records=()
header=$(head -n 1 $datafile)
IFS=$'\t' read -r -a fields <<< "$header"
while IFS=$'\t' read -r -a documents; do
# processing to determine if current row in csv file matches certain criteria
# if it does, the following will happen
for r in ${documents[@]}; do record+="$r"$'\t'; done #appending space instead?
records+="$record"
done < $datafile
for r in "${records[@]}"; do
IFS=$'\t' read -r -a details <<< "$r"
# size of details here is as if record is separated by spaces instead of tabs
for i in "${!fields[@]}" ; do
echo "${fields[i]}: ${details[i]}"
done
done
Example: If this record is process:
Hello World [TAB] nice weather we are having today [TAB] do you agree?
The size of details
should be 3, but I'm getting 11 instead. Why?
bash
, you're probably better off doing it (or most of it) in a language that is better suited to the task, such asawk
orperl
. The code will be shorter, simpler, easier to read and understand, and run much faster than using bash arrays andread
in multiple loops.awk
, and this script does some things that I wasn't really how to get working in awk. You are right; it could certainly be more efficient.