Sample query:
I need to concatenate two strings in bash, so that:
string1=hello
string2=world
mystring=string1+string2
echo mystring
should produce
helloworld
How to concatenate strings in Bash?
In general, to concatenate two variables you can just write them one after another:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
In bash, the best way to do this is:
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
Bash also supports a +=
operator as shown in this code:
A="X Y"
A+=" Z"
echo "$A"
output
X Y Z
Bash first
As this question stand specifically for Bash, my first part of the answer would present different ways of doing this properly:
+=
: Append to variable
The syntax +=
may be used in different ways:
Append to string var+=...
(Because I am frugal, I will only use two variables foo
and a
and then re-use the same in the whole answer. 😉
a=2
a+=4
echo $a
24
Using the Stack Overflow question syntax,
foo="Hello"
foo+=" World"
echo $foo
Hello World
works fine!
Append to an integer ((var+=...))
variable a
is a string, but also an integer
echo $a
24
((a+=12))
echo $a
36
Append to an array var+=(...)
Our a
is also an array of only one element.
echo ${a[@]}
36
a+=(18)
echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18
Note that between parentheses, there is a space-separated array. If you want to store a string containing spaces in your array, you have to enclose them:
a+=(one word "hello world!" )
bash: !": event not found
Hmm.. this is not a bug, but a feature… To prevent bash to try to develop !"
, you could:
a+=(one word "hello world"! 'hello world!' $'hello world\041')
declare -p a
declare -a a='([0]="36" [1]="18" [2]="one" [3]="word" [4]="hello world!" [5]="h
ello world!" [6]="hello world!")'
printf
: Re-construct variable using the builtin command
The printf
builtin command gives a powerful way of drawing string format. As this is a Bash builtin, there is a option for sending formatted string to a variable instead of printing on stdout
:
echo ${a[@]}
36 18 one word hello world! hello world! hello world!
There are seven strings in this array. So we could build a formatted string containing exactly seven positional arguments:
printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'
Or we could use one argument format string which will be repeated as many argument submitted…
Note that our a
is still an array! Only first element is changed!
declare -p a
declare -a a='([0]="36./.18...'\''one'\'' '\''word'\'', '\''hello world!'\''=='\
''hello world!'\''=='\''hello world!'\''" [1]="18" [2]="one" [3]="word" [4]="hel
lo world!" [5]="hello world!" [6]="hello world!")'
Under bash, when you access a variable name without specifying index, you always address first element only!
So to retrieve our seven field array, we only need to re-set 1st element:
a=36
declare -p a
declare -a a='([0]="36" [1]="18" [2]="one" [3]="word" [4]="hello world!" [5]="he
llo world!" [6]="hello world!")'
One argument format string with many argument passed to:
printf -v a[0] '<%s>\n' "${a[@]}"
echo "$a"
<36>
<18>
<one>
<word>
<hello world!>
<hello world!>
<hello world!>
Using this syntax:
foo="Hello"
printf -v foo "%s World" $foo
echo $foo
Hello World
Note: The use of double-quotes may be useful for manipulating strings that contain spaces
, tabulations
and/or newlines
printf -v foo "%s World" "$foo"
Shell now
Under POSIX shell, you could not use bashisms, so there is no builtin printf
.
Basically
But you could simply do:
foo="Hello"
foo="$foo World"
echo $foo
Hello World
Formatted, using forked printf
If you want to use more sophisticated constructions you have to use a fork (new child process that make the job and return the result via stdout
):
foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World
Historically, you could use backticks for retrieving result of a fork:
foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World
But this is not easy for nesting:
foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013
with backticks, you have to escape inner forks with backslashes:
foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013
Concatenate string variables in Bash- Answer #2:
The way I’d solve the problem is just
$a$b
For example,
a="Hello"
b=" World"
c=$a$b
echo "$c"
which produces
Hello World
If you try to concatenate a string with another string, for example,
a="Hello"
c="$a World"
then echo "$c"
will produce
Hello World
with an extra space.
$aWorld
doesn’t work, as you may imagine, but
${a}World
produces
HelloWorld
You can do this too:
$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh
Summary
Here is a concise summary of what most answers are talking about.
Let’s say we have two variables and $1 is set to ‘one’:
set one two
a=hello
b=world
The table below explains the different contexts where we can combine the values of a
and b
to create a new variable, c
.
Context | Expression | Result (value of c)
--------------------------------------+-----------------------+---------------------
Two variables | c=$a$b | helloworld
A variable and a literal | c=${a}_world | hello_world
A variable and a literal | c=$1world | oneworld
A variable and a literal | c=$a/world | hello/world
A variable, a literal, with a space | c=${a}" world" | hello world
A more complex expression | c="${a}_one|${b}_2" | hello_one|world_2
Using += operator (Bash 3.1 or later) | c=$a; c+=$b | helloworld
Append literal with += | c=$a; c+=" world" | hello world
A few notes:
- enclosing the RHS of an assignment in double quotes is generally a good practice, though it is quite optional in many cases
+=
is better from a performance standpoint if a big string is being constructed in small increments, especially in a loop- use
{}
around variable names to disambiguate their expansion (as in row 2 in the table above). As seen on rows 3 and 4, there is no need for{}
unless a variable is being concatenated with a string that starts with a character that is a valid first character in shell variable name, that is alphabet or underscore.
Hope you learned something from this post.
Follow Programming Articles for more!