ElToro1966
ElToro1966

Reputation: 901

Why doesn't this split string expression give me an array?

I am wondering why this array expression in Bash doesn't give me an array. It just gives me the first element in the string:

IFS='\n' read -r -a POSSIBLE_ENCODINGS <<< $(iconv -l)

I want to try out all available encodings to see how reading different file encodings for a script in R works, and I am using this Bash-script to create text-files with all possible encodings:

#!/bin/bash

IFS='\n' read -r -a POSSIBLE_ENCODINGS <<< $(iconv -l)
echo "${POSSIBLE_ENCODINGS[@]}"

for CURRENT_ENCODING in "${POSSIBLE_ENCODINGS[@]}"
do
        TRIMMED=$(echo $CURRENT_ENCODING | sed 's:/*$::')
        iconv --verbose --from-code=UTF-8 --to-code="$TRIMMED" --output=encoded-${TRIMMED}.txt first_file.txt
        echo "Current encoding: ${TRIMMED}"
        echo "Output file:encoded-${TRIMMED}.txt"
done

EDIT: Code edited according to answers below:

#!/bin/bash

readarray -t possibleEncodings <<< "$(iconv -l)"
echo "${possibleEncodings[@]}"

for currentEncoding in "${possibleEncodings[@]}"
do
        trimmedEncoding=$(echo $currentEncoding | sed 's:/*$::')
        echo "Trimmed encoding: ${trimmedEncoding}"
        iconv --verbose --from-code=UTF-8 --to-code="$trimmedEncoding" --output=encoded-${trimmedEncoding}.txt first_file.txt
        echo "Current encoding: ${trimmedEncoding}"
        echo "Output file:encoded-${trimmedEncoding}.txt"
done

Upvotes: 1

Views: 119

Answers (2)

Inian
Inian

Reputation: 85800

You could just readarray/mapfile instead which are tailor made for reading multi-line output into an array.

mapfile -t possibleEncodings < <(iconv -l)

The here-strings are useless, when you can just run the command in a process-substitution model. The <() puts the command output as if it appears on a file for mapfile to read from.

As for why your original attempt didn't work, you are just doing the read call once, but there is still strings to read in the subsequent lines. You either need to read till EOF in a loop or use the mapfile as above which does the job for you.

As a side-note always use lowercase letters for user defined variable/array and function names. This lets you distinguish your variables from the shell's own environment variables which are upper-cased.

Upvotes: 2

Nahuel Fouilleul
Nahuel Fouilleul

Reputation: 19315

because read reads only one line, following while can be used

arr=()
while read -r line; do
    arr+=( "$line" )
done <<< "$(iconv -l)"

otherwise, there is also readarray builtin

readarray -t arr <<< "$(iconv -l)"

Upvotes: 1

Related Questions