In no case is it possible to assign a zero byte $'\0' to a variable.
A string in c ends in a zero byte, it could not contain a zero byte.
No further discussion of this issue follows.
Variables with No spaces, tabs or newlines
If you don't need to allow spaces or newlines, this will work robustly:
if (IFS=''; reg=$'[ \t\n]'; [[ "$*" =~ $reg ]] ); then
echo "$0: error: input contains spaces, tabs or newlines" >&2
exit 1
fi
if (( $# != 4 )); then
echo "$0: error: we need 4 arguments"
exit 2
fi
read x y z k <<<"$@"
printf 'x="%s" y="%s" z="%s" k="%s"\n' "$x" "$y" "$z" "$k"
If the input has either spaces, tabs or newlines the script will barf.
Use it as:
$ script one two t33 f44
x="one" y="two" z="t33" k="f44"
Variables with no newlines
To make it accept spaces and tabs, we need to extend the read to:
IFS=$'\n' read -d '' x y z k < <(printf '%s\n' "$@")
$ ./script $'o\tne' 't wo' t33 f44
x="o ne" y="t wo" z="t33" k="f44"
One reasonable alternative is to use Associative Arrays (no newlines):
if (IFS=''; reg=$'[\n]'; [[ "$*" =~ $reg ]] ); then
echo "$0: error: input contains newlines" >&2
exit 1
fi
varlist=(x y z k)
n=${#varlist[@]}
if (( $# != $n )); then
echo "$0: error: we need $n arguments"
exit 2
fi
declare -A arr
for i in ${varlist[@]}; do
IFS='' read "arr[$i]"
done < <(printf '%s\n' "$@")
for i in ${!arr[@]}; do
printf '%s="%s" ' "$i" "${arr[$i]}"
done
echo
Some changes allow to use directly variable names:
if (IFS=''; reg=$'[\n]'; [[ "$*" =~ $reg ]] ); then
echo "$0: error: input contains newlines" >&2
exit 1
fi
varlist=(x y z k)
n=${#varlist[@]}
if (( $# != $n )); then
echo "$0: error: we need $n arguments"
exit 2
fi
for i in ${varlist[@]}; do
IFS='' read "$i"
done < <(printf '%s\n' "$@")
for i in ${varlist[@]}; do
printf '%s="%s" ' "$i" "${!i}"
done
echo
And a final adaptation allow to finally accept also newlines:
varlist=(x y z k)
n=${#varlist[@]}
if (( $# != $n )); then
echo "$0: error: we need $n arguments"
exit 2
fi
for i in ${varlist[@]}; do
IFS='' read -d '' "$i"
done < <(printf '%s\0' "$@")
for i in ${varlist[@]}; do
printf '%s="%s" ' "$i" "${!i}"
done
echo