Slander
Slander

Reputation: 225

How to create a dynamic variable array name and fill it with multi-line text in bash script

I need to create a dynamic variable name for some arrays and fill it with multi-line text.

What I actually have is this :

#!/bin/bash

IFS=$'\n'
# Set an array with 1 item
ARRAY=("Item1")
# Get a description for the last item from a simple text file
DESCRIPTION=("$(cat test1.txt)")
# Get the number of items in the array
ARRAY_ITEMS_COUNT=${#ARRAY[@]}
# Create a variable name containing the number of items in the array as identifier
# and fill it with the description
eval ARRAY_ITEM${ARRAY_ITEMS_COUNT}_DESCRIPTION="(\"${DESCRIPTION[@]}\")"

# Display some results
echo "ARRAY_ITEM1_DESCRIPTION[@] = \"${ARRAY_ITEM1_DESCRIPTION[@]}\""
echo "ARRAY_ITEM1_DESCRIPTION[0] = \"${ARRAY_ITEM1_DESCRIPTION[0]}\""
echo "ARRAY_ITEM1_DESCRIPTION[1] = \"${ARRAY_ITEM1_DESCRIPTION[1]}\""

echo

# Same as above with a different text file
ARRAY=("Item1" "Item2")
DESCRIPTION=("$(cat test2.txt)")
ARRAY_ITEMS_COUNT=${#ARRAY[@]}

# Get an error here due to the ' character used in the text file
eval ARRAY_ITEM${ARRAY_ITEMS_COUNT}_DESCRIPTION="(\"${DESCRIPTION[@]}\")"

echo "ARRAY_ITEM2_DESCRIPTION[@] = \"${ARRAY_ITEM2_DESCRIPTION[@]}\""
echo "ARRAY_ITEM2_DESCRIPTION[0] = \"${ARRAY_ITEM2_DESCRIPTION[0]}\""
echo "ARRAY_ITEM2_DESCRIPTION[1] = \"${ARRAY_ITEM2_DESCRIPTION[1]}\""

The files "test1.txt" and "test2.txt" are as follow :

test1.txt

Simple text file with multi-lines used as
a test without special characters inside.

test2.txt

Simple text file with multi-lines used as
a test with single ' and double " quotes.

Expected result :

ARRAY_ITEM1_DESCRIPTION[@] = "Simple text file with multi-lines used as
a test without special characters inside."
ARRAY_ITEM1_DESCRIPTION[0] = "Simple text file with multi-lines used as"
ARRAY_ITEM1_DESCRIPTION[1] = "a test without special characters inside."

ARRAY_ITEM2_DESCRIPTION[@] = "Simple text file with multi-lines used as
a test with single ' and double " quotes."
ARRAY_ITEM2_DESCRIPTION[0] = "Simple text file with multi-lines used as"
ARRAY_ITEM2_DESCRIPTION[1] = "a test with single ' and double " quotes."

Current result :

ARRAY_ITEM1_DESCRIPTION[@] = "Simple text file with multi-lines used as
a test without special characters inside."
ARRAY_ITEM1_DESCRIPTION[0] = "Simple text file with multi-lines used as
a test without special characters inside."
ARRAY_ITEM1_DESCRIPTION[1] = ""

./test.sh: eval: line 28: unexpected EOF while looking for matching `"'
./test.sh: eval: line 29: syntax error: unexpected end of file
ARRAY_ITEM2_DESCRIPTION[@] = ""
ARRAY_ITEM2_DESCRIPTION[0] = ""
ARRAY_ITEM2_DESCRIPTION[1] = ""

I tried a lot of things but it never gives me what is expected, so can someone help me solve the 2 issues I have there please :

EDIT : Working solution (bash version > 4) is :

#!/bin/bash

# Set an array with 1 item
ARRAY=("Item1")
# Get the number of items in the array
ARRAY_ITEMS_COUNT=${#ARRAY[@]}
# Create a variable name containing the number of items in the array as identifier
# and fill it with the description
readarray -t "ARRAY_ITEM${ARRAY_ITEMS_COUNT}_DESCRIPTION" < test1.txt

# Display some results
echo "ARRAY_ITEM1_DESCRIPTION[@] = \"${ARRAY_ITEM1_DESCRIPTION[@]}\""
echo "ARRAY_ITEM1_DESCRIPTION[0] = \"${ARRAY_ITEM1_DESCRIPTION[0]}\""
echo "ARRAY_ITEM1_DESCRIPTION[1] = \"${ARRAY_ITEM1_DESCRIPTION[1]}\""

echo

# Same as above with a different text file
ARRAY=("Item1" "Item2")
ARRAY_ITEMS_COUNT=${#ARRAY[@]}

# Get an error here due to the ' character used in the text file
readarray -t ARRAY_ITEM${ARRAY_ITEMS_COUNT}_DESCRIPTION < test2.txt

echo "ARRAY_ITEM2_DESCRIPTION[@] = \"${ARRAY_ITEM2_DESCRIPTION[@]}\""
echo "ARRAY_ITEM2_DESCRIPTION[0] = \"${ARRAY_ITEM2_DESCRIPTION[0]}\""
echo "ARRAY_ITEM2_DESCRIPTION[1] = \"${ARRAY_ITEM2_DESCRIPTION[1]}\""

Thanks for your help, have a nice day.

Slander

Upvotes: 1

Views: 346

Answers (1)

Saucier
Saucier

Reputation: 4370

When you call cat in an array assignment you shouldn't quote it if you want the file to be read line by line. Because if you do so the contents of the file will be handled as one string/one line. So it won't get read line by line. Just try:

DESCRIPTION=($(cat test1.txt))

Also if you are using Bash version 4 you could use bash builtin command readarray to generate an array:

readarray -t DESCRIPTION < "test1.txt"

For Bash version < 4 this could be an alternative to cat and readarray:

IFS=$'\n' read -d -r -a DESCRIPTION < "test1.txt"

Upvotes: 2

Related Questions