0

I have a bash function that reads a csv file and I want that function to return an array. How do I do that?

I know that typically bash does not "return objects" but I wonder if there's a hack so that the following code:

data=$(readFromCSV $file)

returns an array from the custom function readFromCSV. And I mean $data being a true array so I could for instance run

echo {#data[@]}

and it would tell me how many items are in the array.

how would you tell the function to return the array?

thanks

Bluz
  • 5,980
  • 11
  • 32
  • 40
  • 3
    Arrays are not values in `bash`. There is only array *syntax* that lets you treat a single name as a collection of separate variables. – chepner Oct 04 '21 at 13:34
  • 1
    https://stackoverflow.com/questions/10582763/how-to-return-an-array-in-bash-without-using-globals https://stackoverflow.com/questions/56456794/how-to-return-array-from-bash-function https://stackoverflow.com/questions/14839199/returning-array-from-a-bash-function https://stackoverflow.com/questions/25291347/how-to-return-an-array-from-a-script-in-bash – KamilCuk Oct 04 '21 at 13:37

1 Answers1

-1

so basically this is how I proceeded to imitate "an array object" to be passed from a csv file.

First, create the function for the csv:

function readFromCSV() {
    file=$1
    arr_csv=() 
    while IFS= read -r line 
    do
        arr_csv+=("$line")
    done < $file

    echo ${arr_csv[*]} # this will output a string
}

then call the function:

list=$(readFromCSV $file)

then remap the string to an array:

arrayCSV=($list)

now arrayCSV is an array of the values frome the CSV file.

Bluz
  • 5,980
  • 11
  • 32
  • 40
  • 1
    There's no point in defining the array inside the function. You'll get the exact same behavior if you just write each line to standard output: `while IFS= read -r line; do echo "$line"; done < "$file"`. – chepner Oct 04 '21 at 15:11
  • Re: `function funcName() {`, see https://wiki.bash-hackers.org/scripting/obsolete -- this merges legacy ksh and POSIX syntax in a way that isn't compatible with _either_ legacy ksh or POSIX. – Charles Duffy Oct 04 '21 at 15:15
  • ...and as for the actual immediate question at hand, this is very broken code for no good reason. Bash 4.3 namerefs let you _directly_ assign to a caller-named array from within a function. When you use `echo ${arr_csv[*]}`, you defeat the point of ever using an array in the first place, because you destroy the information about where element boundaries were originally stored. – Charles Duffy Oct 04 '21 at 15:16
  • To provide a concrete example, `array=( "first element" "*" "third element" )` -- now when you `string=$(echo ${array[*]})` and use `newArray=( $string )`, you get `newArray[0]="first"`, `newArray[1]="element"`, a list of filenames in the third element onward, etc; you've lost the information that `first element` was ever just one string, and that `*` was quoted. – Charles Duffy Oct 04 '21 at 15:17
  • @chepner, not the exact same behavior -- if one just echo'd a line at a time to stdout you could use `readarray` or `mapfile` to construct an array with correct boundaries on the outside, assuming no array elements contain literal newlines (not a 100% safe assumption, granted, being why NUL delimiters are better). What the OP is doing here is worse; their `echo` puts everything onto one line. – Charles Duffy Oct 04 '21 at 15:24