1

I am trying to create an array from a file. In the troubleshooting process, I hope to print out all elements of the array to convince myself I'm doing it correctly. However, when I use a hard coded array vs an array constructed from a file, I get different results when trying to output all the array elements.

When I hard code an array like this:

matches=("SviPEND18C_0002" "SviPEND18C_0006")

To get output, I use:

echo "${matches[@]}"

which gives me

SviPEND18C_0002 SviPEND18C_0006

And when I use:

printf '%s\n' "${matches[@]}"

I get:

SviPEND18C_0002
SviPEND18C_0006

All that makes sense to me. However, when I try to make an array from a file and get the output, I don't understand the results. I have a text file (L0316_F.txt) with a single column of sample names, like in the matches array above, but with 50 total. Here's how I put them into an array

mapfile -t IDfemales < <(awk '{print $1}' ../L0316_F.txt)

Now when I use echo as above:

echo "${IDfemales[@]}"

I get the last element of the array only. I was expecting all 50 elements on a single line.

echo "${IDfemales}"

I get the first element of the array only.

However, when I use printf as above:

printf '%s\n' "${IDfemales[@]}"

I get all 50 elements, 1 element per line.

I have already looked at https://stackoverflow.com/questions/41150814/how-to-echo-all-values-from-array-in-bash and I don't get the same results they do.

I would love an explanation. Eventually, I plan to match the elements in the array to file names, which isn't working for me right now, and I assume it's because I don't understand how the array is stored.

9
  • 5
    Possible explanation: Your file has dos line endings, so all text is printed on one line with echo. Remove dos line endings. See dos2unix and cat -v and hexdump -C. Check the output of declare -p IDfemales
    – KamilCuk
    Commented Jan 28 at 19:51
  • I suspect KamilCuk is right. Try awk '{sub(/\r$/, "", $1); print $1}. You do understand how the array is stored, it's just this hidden carriage return that makes the echo output confusing. Do this: inspect the array with declare -p IDfemales Commented Jan 28 at 19:59
  • 1
    @glenn jackman declare -p IDfemales gives me ")'49]="SviPEND18C_0149[0]="SviPEND18C_0002. I have no idea what this means. SviPEND18C_0149 is the last element in the array and SviPEND18C_0002 is the first element.
    – coyk
    Commented Jan 28 at 20:19
  • @KamilCuk When I use echo I don't get all the text on 1 line. I only get the last element of the array ("${IDfemales[@]}") or the first element of the array ("${IDfemales}")
    – coyk
    Commented Jan 28 at 20:22
  • 1
    Comments are formatting badly. Consider posting the output by editing the question. I use echo I don't get all the text on 1 line You do, but the single line is overwritten over and over again, and what is visible on the end is only the last line. Check cat -v ../L0316_F.txt of your file. Run your file through dos2unix or through that awk command.
    – KamilCuk
    Commented Jan 28 at 20:30

1 Answer 1

3

echo prints each argument separated by a space then adds a newline at the end.

printf '%s\n' prints each argument with a new line as it repeats the format string as long as there are elements to consume.

#!/usr/bin/env bash

# Populates array
arr=(foo bar baz cuux)

printf 'Output from echo:\n'
echo "${arr[@]}"

printf '\nOutput from printf:\n'
printf '%s\n' "${arr[@]}"

results:

Output from echo:
foo bar baz cuux

Output from printf:
foo
bar
baz
cuux

If you want the output of printf be like the output of echo, expand the array as a single argument:

#!/usr/bin/env/bash

# Populates array
arr=(foo bar baz cuux)

# Print all entries as one argument (similar to echo)
printf '%s\n' "${arr[*]}"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.