How to use mapfile

7,561

Solution 1

It seems to me that you're wanting to loop through your array, reading the elements into columns:

for ele in "${TEST_ARR[@]}"
do
  read -r col1 col2 col3 col4 col5 col6 col7 col8 TRASH <<< "$ele"
  echo -e "${col1}\n${col2}\n${col3}\n${col4}\n${col5}\n${col6}\n"
done

Solution 2

mapfile reads the contents of a file to an array, and if you use "${array[@]}" in a context like an assignment or <<< that takes only a single string, it concatenates all the array elements to a single string. A bit like "${array[*]}", except @ joins with spaces, and * with the first character of IFS.

Now, you said you "created a mapfile", but I don't think that's how the command name is supposed to be interpreted. It's more like that it "maps" a file to an array. (Except that it's a copy, not a two-way mapping like it might be in some languages.) The alternative name of readarray is probably more accurate.

Share:
7,561

Related videos on Youtube

jesse_b
Author by

jesse_b

I'm not a spy for the CIA.

Updated on September 18, 2022

Comments

  • jesse_b
    jesse_b over 1 year

    I have some code similar to this:

    while read -r col1 col2 col3 col4 col5 col6 col7 col8 TRASH; do 
            echo -e "${col1}\n${col2}\n${col3}\n${col4}\n${col5}\n${col6}\n"
    done< <(ll | tail -n+2 | head -2)
    

    (I'm not actually using ls / ll but I believe this redacted example displays the same issue I am having)

    The problem is I need a conditional statement if ll | tail -n+2 | head -2 fails so I'm trying to create a mapfile instead and then read through it in a script. The mapfile gets created properly but I don't know how to redirect it in order to be properly read.

    code

    if ! mapfile -t TEST_ARR < <(ll | tail -n+2 | head -2); then
            exit 1
    fi
    while read -r col1 col2 col3 col4 col5 col6 col7 col8 TRASH; do 
            echo -e "${col1}\n${col2}\n${col3}\n${col4}\n${col5}\n${col6}\n"
    done<<<"${TEST_ARR[@]}"
    

    mapfile contents

    declare -a TEST_ARR=(
            [0]="drwxr-xr-x@ 38 wheel   1.2K Dec  7 07:10 ./" 
            [1]="drwxr-xr-x  33 wheel   1.0K Jan 18 07:05 ../"
    )
    

    output

    $ while read -r col1 col2 col3 col4 col5 col6 col7 col8 TRASH; do
    >             echo -e "${col1}\n${col2}\n${col3}\n${col4}\n${col5}\n${col6}\n"
    >     done<<<"${TEST_ARR[@]}"
    drwxr-xr-x@
    38
    wheel
    1.2K
    Dec
    7
    

    String redirect is clearly wrong in this case but I'm not sure how else I can redirect my array.

    • Alessio
      Alessio over 6 years
    • jesse_b
      jesse_b over 6 years
      @cas Please read my post.
    • Alessio
      Alessio over 6 years
      I read it, and saw you were trying to parse ls. So i posted a link to a Q&A detailing why that's a bad idea and what you can/should do instead. What you do with that information is up to you.
    • jesse_b
      jesse_b over 6 years
      "(I'm not actually using ls / ll but I believe this redacted example displays the same issue I am having)" - Me
    • Alessio
      Alessio over 6 years
      "Redacted" doesn't mean what you think it does. It means censored, all private/confidential/sensitive parts removed - not "completely made up". So, "redacted example" means "real data, anonymised" not "convenient placeholder data with no resemblance to the real data". In any case, it's a bad made-up example to use because other people will read it and think they can parse ls if they use this the answers given here.
    • jesse_b
      jesse_b over 6 years
      @cas redacted means exactly what I think it means. :). The command itself has been redacted.
    • Alessio
      Alessio over 6 years
      Bravo! it only took you 4 days to come up with that witty, albeit inaccurate, retort.
  • jesse_b
    jesse_b over 6 years
    Thanks! I wasn't aware I could use read that way and had a method for setting all my variables with awk but it would not have been efficient. This is great!