You can add a string to a number using simple concatenation:
$ i=3
$ echo n$i
n3
however that doesn't help much with your real goal here, which seems to be how to assign an indeterminate number of user inputs to indexed variables.
As you've already discovered, you can't use variables named 1
, 2
, 3
etc. in a read
command. Aside from the fact that bash variable names must at least begin with an alphabetic character or an underscore, the expansions $1
, $2
, $3
and so on are reserved for the shell's positional parameters.
If you really want to use $1
... $n
in your script, you can actually do so using the set
shell builtin. Note that whereas POSIX only requires support for parameters up to $9
, bash supports an arbitrary number (although for indexes above 9 you will need to use braces to disambiguate between, for example, ${10}
as the 10th positional parameter and $10
as the concatenation of $1
with literal 0
). For example:
#!/bin/bash
set --
while : ; do
read -n1
case $REPLY in
[01]) set -- "$@" "$REPLY"
;;
*) break
;;
esac
done
for ((i=1; i<=$#; ++i)); do
printf 'Digit #%d = %d\n' "$i" "${!i}"
done
The user enters a sequence of 0
and 1
characters, terminating the sequence by hitting any other character (including newline):
$ ./bin2dec
1011010110
Digit #1 = 1
Digit #2 = 0
Digit #3 = 1
Digit #4 = 1
Digit #5 = 0
Digit #6 = 1
Digit #7 = 0
Digit #8 = 1
Digit #9 = 1
Digit #10 = 0
Alternatively, you could do essentially the same with a user-defined array:
#!/bin/bash
arr=()
while : ; do
read -n1
case $REPLY in
[01]) arr+=("$REPLY")
;;
*) break
;;
esac
done
for ((i=0; i<${#arr[@]}; ++i)); do
printf 'Digit #%d = %d\n' "$i" "${arr[i]}"
done
Note the different indexing; although both arrays are zero-based, the zeroth element of $@
is reserved for the name of the script file.