2

I have this code:

#!/bin/sh

...

for cnumber in `seq $CNUMBER`; do
    declare -a CAT$cnumber
    let i=0
    while IFS=$'\n' read -r line_data; do
        CAT$cnumber[i]="${line_data}"
        ((++i))
    done < input_file_$cnumber
done

It works if I use array name without variable $cnumber.

But I want to create multiple arrays (CAT0, CAT1, CAT2 etc.) and to read lines:

from file 'input_file_0' to array 'CAT0'
from file 'input_file_1' to array 'CAT1'
from file 'input_file_2' to array 'CAT2'
etc.

What syntax to use $cnumber variable in array name (CAT1) and in input file_name?

2
  • Try to concat the number i.e CAT{$cnumber}. Let me know if it is working Commented Dec 28, 2014 at 22:25
  • I think you mean CAT${cnumber} Commented Dec 28, 2014 at 22:29

2 Answers 2

1
for cnumber in `seq $CNUMBER`; do
    declare -a CAT$cnumber
    let i=0
    while IFS=$'\n' read -r line_data; do
        eval CAT$cnumber[i]='"${line_data}"'
        ((++i))
    done < input_file_$cnumber
done

Mainly, that adds the word "eval" which makes bash evaluate the rest of the line. Before that, bash expands variables, thus CAT$number will be something like CAT1 when the line is evaluated. Keep in mind that "${line_date}" would be subject to variable expansion before eval evaluates the line if it would not be protected by single quotes. That might have unexpected effects if the $line_data would contain blank spaces. See this simplified example:

a=b
l="hello date"
eval $a="$l"    # executes "date", has no other effect
echo $b         # prints an empty line
eval $a='"$l"'  # sets b to "hello date"
echo $b         # prints that: hello date

In reply to the comment of Etan Reisner below, I add another solution that avoids "eval" and instead uses references, which are available in bash version 4.3 or higher. In that case, using references is preferable for the reason Etan pointed out, and also, for my opinion, because it is more natural:

for cnumber in `seq $CNUMBER`; do
    declare -a CAT$cnumber      # be sure the array is declared before ...
    declare -n ref=CAT$cnumber  # ... you declare ref to reference the array
    let i=0
    while IFS=$'\n' read -r line_data; do
        ref[$i]="${line_data}"
        ((++i))
    done < input_file_$cnumber
done
Sign up to request clarification or add additional context in comments.

1 Comment

It should be pointed out that using eval has serious security implications unless variables are controlled very carefully. And given this snippet unless the CAT## arrays need to persist beyond the loop using a constructed variable name like this is likely entirely pointless. Also an indirect reference here would likely work as well and be safer.
0

First, your shebang needs to be

#!/bin/bash

since declare is a bash built-in.

Next, use declare to define the array elements

for cnumber in `seq $CNUMBER`; do
    declare -a CAT$cnumber
    let i=0
    while IFS=$'\n' read -r line_data; do
        declare "CAT$cnumber[$i]=${line_data}"
        ((++i))
    done < input_file_$cnumber
done

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.