How to concatenate strings in Bash?

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 spacestabulations 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!

About ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ

Linux and Python enthusiast, in love with open source since 2014, Writer at programming-articles.com, India.

View all posts by ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ →