5

I have a bash array OUTARRAY that I fill will values from processing an INARRAY. I frequently append to OUTARRAY special chars, namely \t and \n so it may look like:

OUTARRAY[j]="\n"

or

OUTARRAY[j]="${INARRAY[i]}\t"

in the end I dump the OUTARRAY in a file using

printf "%s" "${OUTARRAY[@]}" > ${OUTFILE}

the result I get however is, a single line file with all the special chars printed within:

\n2771\t2899\t7624\t2911\t\n2772\t2904\t7706\t2911\t\n2771\t2909

Instead, I want columned output. Something like

2771    2899    7624    2911
2772    2904    7706    2911

and so on. what do I do wrong? thank you

3 Answers 3

5

bash does not interpret C-style backslash escapes (\n) in quoted strings.

Instead, use the bash syntax $'\n':

OUTARRAY[j]=$'\n'
OUTARRAY[j]="${INARRAY[i]}"$'\t'

You might find it more readable if you start by defining:

NL=$'\n'
TAB=$'\t'

and then you can insert ${NL} and ${TAB} freely inside your double-quoted strings.


Alternatively, you can use a bash extension:

printf normally expands C-style backslash escapes in formats, but not in arguments. However, if you are using bash, then you can use the bash-specific %b printf format which expands backslash escapes in the corresponding argument. I don't really endorse this solution, but it should work without other modifications:

printf "%b" "${OUTARRAY[@]}" > ${OUTFILE}

By the way, it is not really good style to use ALL CAPS for bash variable names, because it increases the probability that they will clash with bash/system-specific environment variables.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh, it seems we have exactly the same answer... so I can only +1 yours :).
@gniourf_gniourf There are not so many ways to answer the question :)
5

Instead of inserting the string \t or \n, insert actual tabs and newlines:

outarray[j]=$'\n'
outarray[j]=${inarray[i]}$'\t'

Now this is not really a good strategy. Instead, do not put your formatting in the array, but use printf to format how you want your array to be displayed: if you want 4 fields per line, separated by tabs:

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

(btw, I lowercased your variable names, it's much better).

2 Comments

for reasons of parsing strength, I prefer not to assume I'll always have 4 columns :) this would be a good way otherwise.
@nass: you can build your format string dynamically to take that into account!
1

The other answers are the right way to do it but it is possible to print your data as it is. You can use echo -ne and a loop to print your values:

$ arr=( "a\t" "b\n" "c\t" "d\n" )
$ for i in "${arr[@]}"; do echo -ne $i; done
a       b
c       d

The -n switch to echo removes the trailing newline and the -e means that backslash escape characters will be interpreted.

3 Comments

Yes, that's another quick possibility too! (with caveats too). +1 anyways. :).
As gniourf_gniourf notes, printf is much more elegant if you have a consistent number of columns.
I readily acknowledge that both of your alternatives are superior, I just thought that echo deserved a mention. +1 to both of you.

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.