Motivation

Was working on a Stack Overflow question and found myself working on a Bash script which converts csv into a Bash array. What if we wanted to access the second field of the csv and only that? Using grep/cut is the obvious solution but the method below would demonstrate another way to achieve it. This helped me understand Bash better.

The solution

  • Make use of the read command. The command reads a file line by line. Say we want to loop through every row until the 5th row in a csv file called input.csv. While we do that, we only grab the first field of the csv file and write the results into a text file.
  • The key: use the -a flag for the read command. This will create an indexed array.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #!/bin/bash

    # this script grabs only the first field of the first 5 rows of a csv file
    {
    # initialize var to 0
    var=0
    # set while condition so loop terminates after reading 5 lines
    while (( var < 5 ))
    do
    # set separator to "," and specify "-a" flag
    IFS=, read -a arr
    # increment var by 1 after every iteration
    var=$(( var+1 ))
    echo "${arr[0]}" >> output.txt
    #echo $var
    done
    } < input.csv

Extra snippet

  • You can manually declare an indexed array too! Use the declare command.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# first let's declare an array variable
# -a flag results in an indexed array
declare -a arr=("string1" "string2" "string3")

# now let's loop through the created array (arr)
# notice we use "@" to access ALL the strings in arr
for i in "${arr[@]}"
do
echo "$i"
done
# you can specify the index of the string you want to access
# remember, the array starts with index 0!

# multi-line array declaration is supported e.g.
# makes your code a tad bit cleaner with many strings
declare -a arr=("string1"
"string2"
"string3")

References

Loop through an array of strings in Bash?