How to use 'readarray' in bash to read lines from a file into a 2D array

后端 未结 6 1743
旧时难觅i
旧时难觅i 2021-02-04 06:35

Let\'s say I have a text file \'demo.txt\' who has a table in it like this:

1 2 3    
4 5 6    
7 8 9    

Now, I want to read each line separat

相关标签:
6条回答
  • 2021-02-04 06:48

    How can accesses each line separately and in that line get access to each member?

    Per the Bash Reference Manual, Bash provides one-dimensional indexed and associative array variables. So you cannot expect matrix[1][2] or similar to work. However, you can emulate matrix access using a bash associative arrays, where the key denotes a multiple dimension.

    For example, matrix[1,2] uses the string "1,2" as the associative array key denoting the 1st row, 2nd column. Combining this with readarray:

    typeset -A matrix
    function load() {
        declare -a a=( $2 )
        for (( c=0; c < ${#a[@]}; c++ ))
        do
            matrix[$1,$c]=${a[$c]}
        done
    }
    readarray -C load -c 1 <<< $'1 2 3\n4 5 6\n7 8 9'
    declare -p matrix
    
    0 讨论(0)
  • 2021-02-04 06:51

    To expand on Damien's answer (and because I can't submit comments yet...) you just iterate on read. What I mean is something like the following

    exec 5<demo.txt
    for i in `seq 1 ${numOfLinesInFile}`
    do
    read -a arr -u 5
      for j in `seq 0 ${numOfColumnsMinus1}`
      do
      echo ${arr[$j]}
      done
    done
    

    I hope you found a solution already (sorry to bump...). I stumbled upon this page while helping teach a friend and figured others may do the same.

    0 讨论(0)
  • 2021-02-04 06:56

    Sorry to bump but I believe there's an easy and very clean solution for your request:

    $ cat demo.txt
    1 2 3
    4 5 6
    7 8 9
    $ while read line;do IFS=' ' myarray+=(${line}); done < demo.txt
    $ declare -p myarray
    declare -a myarray='([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="7" [7]="8" [8]="9")'
    $
    
    0 讨论(0)
  • 2021-02-04 06:58

    This is the expected behavior. readarray will create an array where each element of the array is a line in the input.

    If you want to see the whole array you need to use

    echo "${myarray[@]}"
    

    as echo "$myarray will only output myarray[0], and ${myarray[1]} is the second line of the data.

    What you are looking for is a two-dimensional array. See for instance this.

    If you want an array with the content of the first line, you can do like this:

    $ read -a arr < demo.txt 
    $ echo ${arr[0]}
    1
    $ echo ${arr[1]}
    2
    $ echo ${arr[2]}
    3
    
    0 讨论(0)
  • 2021-02-04 07:08
    readarray rows < demo.txt                                           
    
    for row in "${rows[@]}";do                                                      
      row_array=(${row})                                                            
      first=${row_array[0]}                                                         
      echo ${first}                                                                 
    done 
    
    0 讨论(0)
  • 2021-02-04 07:14

    Since 3 out of 5 answers ignore the OPs request to use readarray I'm guessing no one will downvote me for adding another that also fails to use readarray.

    Paste the following code unaltered into an Ubuntu bash command line (not tried in any other environment)

    Code

    # Create test array
    echo -e "00 01 02 03 04
    10 11 12 13 14
    20 21 22 23 24
    30 31 32 33 34" > original.txt;
    
    # Reformat test array as a declared bash variable.
    sed 's/^/"/g;  s/$/"/g;  1s/^/declare my2d=(\n/;  $s/$/\n);/' original.txt > original.sh;
    
    # Source the bash variable.
    source original.sh;
    
    # Get a row.
    declare row2=(${my2d[2]});
    
    # Get a cell.
    declare cell3=${row2[3]};
    echo -e "Cell [2, 3] holds [${cell3}]";
    

    Output

    Cell [2, 3] holds [23]
    

    Explanation

    The four sed groups do the following:

    1. s/^/"/g; - prepend double quotes to each line
    2. s/$/"/g; - append double quotes to each line
    3. 1s/^/declare my2d=(\n/; - prepend declare my2d=( to file
    4. $s/$/\n); - append );to file

    Note

    This gets too messy to be worth using if your array elements have whitespace in them

    0 讨论(0)
提交回复
热议问题