Severus15
Severus15

Reputation: 127

Bash - how to split an array element into a list

I have a file with a lot of filenames which are formatted like this:

filename1;filename2
filename3;filename4
filename5;filename6

I've managed to read this into an array for now, so I have 1 line per array element. But I need to split every element into two elements, with the semicolon as a delimiter. So I would get something like an array in an array, where the inner one has always 2 elements? As an endresult I'm trying to rename a bunch of files with this array.

How can I split this array, so I get this array within an array?

Upvotes: 0

Views: 306

Answers (1)

Socowi
Socowi

Reputation: 27215

Split an array element into a list

IFS=\; read -ra list <<< "${yourArray[0]}" creates a list/array from your first array entry. But you cannot use that list as intended. Bash supports only 1D arrays. You cannot nest arrays.

Two arrays

Since your number of columns is constant and just 2, you could create one array for each column. This works well if you access col1 and col2 in a static manner only.

mapfile -t a yourFile
col1=("${a[@]/;*/}")
col2=("${a[@]/*;/}")

Fake a 2D array using an associative array

If you need dynamic access (e.g. the column is chosen by a variable) you could use eval or reference variables (declare -n), but the following hack could be better for small arrays and scrips where you access the array at a lot of different places dynamically:

mapfile -t a yourFile
declare -A field
for i in "${!a[@]}"; do
  field["$i,1"]=${a[i]/;*/}
  field["$i,2"]=${a[i]/*;/}
done

That way you can access the field in row $r and column $c using ${field[$r,$c]}.

For files with more than two columns use

mapfile -t a yourFile
declare -A field
for r in "${!a[@]}"; do
  IFS=\; read -ra b <<< "${a[r]}"
  for c in "${!cols[@]}"; do
    field["$r,$c"]=${b[c]}
  done
done

Upvotes: 4

Related Questions