Bash - assign array into variable as string
Solution 1
When IFS='-' read -r -a host_name_array <<< "$(hostname)"
is ran, the array is (tech news blog 324344)
.
After the final element is removed with unset 'host_name_array[${#host_name_array[@]}-1]'
, the array is (tech news blog)
.
So, to get this to echo tech-news-blog
, some substitution will have to be done, since echo "${host_name_array[*]}"
will yield tech news blog
:
With tr: echo "${host_name_array[*]}" | tr ' ' '-'
sed: echo "${host_name_array[*]}" | sed 's/ /-/g'
Solution 2
You could do this by outputting the elements separated by -
, and then strip off the last -
by parameter expansion:
$ var=$(printf '%s-' "${host_name_array[@]}")
$ echo "$var"
foo-bar-spam-egg-
$ var="${var%-}"
$ echo "$var"
foo-bar-spam-egg
Also you need ${host_name_array[@]}
instead of ${host_name_array[*]}
to prevent outputting the elements as a whole separated by first character of IFS
.
What you are trying to do can be achieved by a simple parameter expansion:
${var%-*}
Example:
$ var=$(hostname)
$ echo "${var%-*}"
Solution 3
(...)
introduces a subshell. So $URL
wouldn't be set after that (still have the value it had before the subshell). You want:
IFS=-
read -r -a host_name_array <<< "$(hostname)"
unset 'host_name_array[${#host_name_array[@]}-1]'
URL="${host_name_array[*]}"
"${host_name_array[*]}"
joins the elements on the arrays on the first character of $IFS
just like "$*"
does in standard sh
.
If the reason why you're using a subshell is because you don't want to modify $IFS
globally, you could do that in a function where you give $IFS
a local scope:
f() {
local IFS=-
...
}
f
Or use command substitution that also creates a subshell but allows passing data to the parent shell:
URL=$(IFS=-; printf '%s\n' "${host_name_array[*]}")
Here though I'd use standard sh
expansion to remove that trailing component:
URL=$(uname -n) # uname -n is the standard equivalent of hostname
URL=${URL%-*}
It has several advantages over the above:
- it works even if the text contains newline characters (very unlikely for host names here though);
- if the text doesn't contain
-
, it doesn't remove anything; - it is more efficient.
read <<< $(hostname)
means runninghostname
, read its output through a pipe, storing that in a temp file and haveread
read the first line of that; - it doesn't clobber the variable namespace with those temporary variables
- it is shorter;
- it is portable. No need to install
bash
to run that code. The system'ssh
will suffice.
In any case, remember to quote your variables when using them in list contexts:
printf '%s\n' "$URL"
When doing:
echo $URL
You're invoking the split+glob operator. So, if $IFS
still contains -
, that $URL
would be split on -
, and echo
would output those words separated by spaces.
Related videos on Youtube
BenB
Updated on September 18, 2022Comments
-
BenB over 1 year
I have this code, it prints the correct result, but I can't figure out how to get the echo from the last line into a variable.
# hostname is 'tech-news-blog-324344' . Setting it into array host_name_array IFS='-' read -r -a host_name_array <<< "$(hostname)" #removing the last part of string after last "-" unset 'host_name_array[${#host_name_array[@]}-1]' ( IFS=$'-'; echo "${host_name_array[*]}" ) #result is 'tech-news-blog'
How could get the value of the last line into a variable? I've tried the following:
( IFS=$'-'; URL="${host_name_array[*]}" )
But I get the result "tech news blog" with spaces between pieces of array instead of '-'.
-
BenB over 7 yearsBoth the echo works, but if I try to set that result into a variable and reuse it I get from the variable the string with spaces
-
Kenneth B. Jensen over 7 years
var=$(echo "${host_name_array[*]}" | tr ' ' '-')
, but I think @heemayl's solution is better, since it is much less bulky and awkward. -
BenB over 7 yearsWhen I echo the $var I get the string with spaces for some reason
-
BenB over 7 yearsAbout his answer, I have the same issue there when I echo the $var I get the string with spaces
-
Kenneth B. Jensen over 7 yearsIs IFS still set to '-'? If so, that may be the cause; reset it with
unset IFS
. -
F. Hauri over 7 yearsWow, this is strong! Why did you not use
printf -v var "%s-" ...
syntax? -
F. Hauri over 7 years@heemayl Using
var=$(printf...
implie one fork to subshell, whereprintf -v ...
let you use builtinprintf
and setvar
without forks! This is a lot quicker. -
heemayl over 7 years@F.Hauri I was serious there :) You are absolutely right :)