9

I often print out the contents of an array using a quick printf shorthand like this:

$ printf "%s\n" "${my_array[@]}"
$ printf "%s\0" "${my_array[@]}"

This works great in general:

$ my_array=(limburger stilton wensleydale)
$ printf "%s\n" "${my_array[@]}"
limburger
stilton
wensleydale
$

Works great, but when the array is empty it still outputs a single character (a newline or null byte):

$ my_array=()
$ printf "%s\n" "${my_array[@]}"

$

Of course, I can avoid that by testing first for an empty array:

$ [[ ${#my_array[@]} -gt 0 ]] && printf "%s\n" "${my_array[@]}"
$ (( ${#my_array[@]} )) && printf "%s\n" "${my_array[@]}"

But I use this idiom all the time and would prefer to keep it as short as possible. Is there a better (shorter) solution, maybe a different printf format, that won't print anything at all with an empty array?

2
  • 2
    It seems like the root problem is that printf fills in missing arguments. For example, with a quote spec, it prints the empty string: printf '%q\n' -> ''; and with a number spec, it prints zero: printf '%d\n' -> 0 or printf '%d %d\n' 5 -> 5 0. Commented Jun 12, 2021 at 19:15
  • (( ${#my_array[@]} )) fails in a set -e context. Instead, you may want the equivalent: (( ${#my_array[@]} == 0 )) || printf "%s\n" "${my_array[@]}" Commented Oct 11, 2023 at 8:13

4 Answers 4

7

Bash's parameter expansion might help:

printf "%b" "${my_array[@]/%/\\n}"

From help printf:

%b: expand backslash escape sequences in the corresponding argument

or

printf "%s" "${my_array[@]/%/$'\n'}"
Sign up to request clarification or add additional context in comments.

Comments

4

For what it is worth:

(( ${#my_array[@]} )) && printf "%s\n" "${my_array[@]}"

(( ${#my_array[@]} )) is a Bash's stand-alone arithmetic expression that evaluates to true when array length is greater than 0.

Anyway, when I need to debug the content of an array. I prefer to use:

declare -p my_array

It will clearly show details that a simple printf '%s\n' cannot, like:

  • element key or index,
  • empty elements,
  • elements containing non-printable characters,
  • all of variable type or flags,
  • if array is undeclared, void declare -a my_array= or empty declare -a my_array=().

1 Comment

+1 for declare -p! I thought of it myself but neglected to mention it :) For (( ${#my_array[@]} )), though, OP has tried it already.
3

For what it's worth, a plain old for-loop works like you want. It's not shorter, but it is more obvious, so this is what I'd use for scripts instead of a shorthand.

$ my_array=(limburger stilton wensleydale)
$ for i in "${my_array[@]}"; do printf '%s\n' "$i"; done
limburger
stilton
wensleydale
$ my_array=()
$ for i in "${my_array[@]}"; do printf '%s\n' "$i"; done
$ 

Comments

0

There's no better solution than to test if the array is not empty.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.