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 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. 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}") 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. 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[*]}"
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.