How to concatenate string variables in Bash
Asked Answered
E

31

3535

In PHP, strings are concatenated together as follows:

$foo = "Hello";
$foo .= " World";

Here, $foo becomes "Hello World".

How is this accomplished in Bash?

Encumbrance answered 15/11, 2010 at 5:38 Comment(5)
foo="Hello" foo=$foo" World" echo $foo this rather worked for "#!/bin/sh"Caressa
What to do if you want HelloWorld without space?Incorruptible
@Incorruptible foo1="World" foo2="Hello" foo3="$foo1$foo2" Nathalienathan
spaces does a matter in bash)Caloric
to give an example of inserting into a string do echo "sh ${HOME}/ultimate-utils/run_tb.sh"Untouchable
Z
4785
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World

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
Zedekiah answered 15/11, 2010 at 5:41 Comment(15)
Does there have to be a space in your first example? Is it possible to do something like foo="$fooworld"? I would assume not...Echinate
@Echinate That would look for a variable named fooworld. Disambiguating that is done with braces, as in foo="${foo}world"...Dispel
@Dispel I've found you can also use foo=$foo'world'Blanks
@Blanks Yes, that works as well, although in my opinion it's not quite as good for code clarity... But that may just be my preference... There are a couple other ways it can be done as well - the point is making sure the variable name is separated from the non-variable-name parts so that it parses correctly.Dispel
One problem with putting the whole thing in double quotes, as with foo="$foo World", is that the additional string ("world" in this case) would be interpreted by the shell if it contained variable names, etc, which is usually not wanted. IMO, the common case requires the syntax $foo="$foo"' world'.Varick
The problem with this solution is that it is very inefficient. the value of $foo is copied then the new value is appended, which takes a long time if the string is very long. It becomes especially apparent if you append strings in a loop, then the complexity of the loop becomes quadratic instead of linear.Tache
If i use this code it gives me " world" as output. what can i do to fix this?Urology
Can't print as follows in a single write ? echo 'User Name: $USER'Aspen
In addition to the answer: str="World" echo "Hello "$str. If you want to concatenate a constant string and a variable.Crosspatch
foo="$foo World" this can be extremely slow if the made in a loop with large strings (string growing every iteration). In this case, += very very fasterAyacucho
If you are concerned about performance, see an analysis in my answer https://mcmap.net/q/40378/-how-to-concatenate-string-variables-in-bashOxygen
Note: there are no spaces around =! This will not work: a ='hello', neither will this: a = ' hello', etc.Agonic
@ChamindaBandara variables are not evaluated in single-quote strings. Use echo "User Name: $USER" instead (or better, echo "User Name: ${USER}"). If you absolutely, positively must use single quotes, put the variable outside the single quotes, i.e. echo 'User Name: '$USER.Valse
quite a lot of characters. i would use rather $VAR1""$VAR2. this way i save the curved bracketsLuster
Can I also use echo -e if I want to have newline in between strings as: c="${a}\n${b}"Fulbright
T
1348

Bash also supports a += operator as shown in this code:

A="X Y"
A+=" Z"
echo "$A"

output

X Y Z

Thump answered 15/11, 2010 at 8:33 Comment(10)
Can I use this syntax with the export keyword? e.g. export A+="Z" or maybe the A variable only needs to be exported once?Realm
@levesque: Both :-). Variables only need to be exported once, but export A+=Z works quite nicely as well.Thump
Since this is a bashism, I think it's worth a mention that you should never use #!/bin/sh in a script using this construction.Delanty
It's specifically and only a plus-equals operator. That is, unlike Javascript, in Bash, echo $A+$B prints "X Y+Z"Ramayana
@Delanty What is a bashism? ThanksTriform
A bashism is a shell feature which is only supported in bash and certain other more advanced shells. It will not work under busybox sh or dash (which is /bin/sh on a lot of distros), or certain other shells like the /bin/sh provided on FreeBSD.Delanty
Are there any use cases where this might yield an unpredictable result? Would it be better to create a generic concat function, instead of hoping that the += form does not hit an edge case?Lumbering
@AnthonyRutledge: I am not aware of any edge cases, except for a script not actually using Bash by mistake. Even this works: let A=1; A+=1; echo $A - it prints 11, which is what you'd expect from a string concatenation operator. But I'd argue that if you are worried about edge cases, then you should probably use a "proper" programming language, maybe even one with a proper type system...Thump
I needed to use this += operator. I found that if I tried to put an underscore between the variables that bash would mistakenly think the name of the first variable included the underscore. Example if A=foo and B=bar, then $A$B is foobar, but $A_$B is only bar. Apparently thinks there is a variable named A_. Note that a dash works fine, meaning this case works as expected: $A-$B is foo-bar.Farad
@Farad you have to use {} if your variable reference is followed by another character that might be part of the variable name. Just write ${A}_$B and it will work fine in all shells.Te
C
1101

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' hello\ world\!)

declare -p a
declare -a a='([0]="36" [1]="18" [2]="one" [3]="word" [4]="hello world!" [5]="h
ello world!" [6]="hello world!" [7]="hello world!")'

Where 6 fields (one, word and 4 x hello world!), where added to array ${ar[@]} which already contained 38 and 18.

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!>
<hello world!>

Using the Stack Overflow question syntax:

foo="Hello"
printf -v foo "%s World" $foo
echo $foo
Hello World

Nota: 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

In the other side:

foo=" World"
foo="Hello$foo"
echo "$foo"
Hello World

But if you want to add letters immediately after your variable, without space, you may need to use braces:

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

More..

Playing with strings, have a look at:

Closestool answered 4/8, 2013 at 10:4 Comment(8)
The += operator is also much faster than $a="$a$b" in my tests.. Which makes sense.Richella
This answer is awesome, but I think it's missing the var=${var}.sh example from other answers, which is very useful.Fleurdelis
Is bash the only shell with += operator? I want to see if it is portable enoughGahl
@Gahl no. i'ts surely not the only shell with += operator, but all this ways are bashisms, so not portable! Even you could encounter special bug in case of wrong bash version!Closestool
This is the correct answer IMO, because i was looking for concatenating without spaces, and += works like a charm.Truett
"If you want to store a string containing spaces in your array, you have to enclose them." Can you provide an enclose demo?Terranceterrane
@Terranceterrane There is already a sample: look for a+=(one word "hello world"! 'hello world!' $'hello world\041') where 5 fields will be added to array "${a[@]}"Closestool
@Fleurdelis I've finally added a paragraph under Shell now... ( sorry for the delay 7y7m1d18h40m It's never too late to do well! ;-)Closestool
I
139

You can do this too:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh
Impetuosity answered 28/10, 2011 at 3:9 Comment(3)
While no special chars, nor spaces are used, double quotes, quotes and curly brackets are useless: var=myscript;var=$var.sh;echo $var would have same effects (This work under bash, dash, busybox and others).Closestool
@F.Hauri thank you for pointing that out. But if you were to append a number, it would not work: e.g. echo $var2 does not produce myscript2Alt
@Alt This work because of the dot . illegal in variable name. If else echo ${var}2 or see my answerClosestool
C
126
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"

Will output

helloohaikthxbye

This is useful when $blaohai leads to a variable not found error. Or if you have spaces or other special characters in your strings. "${foo}" properly escapes anything you put into it.

Caracalla answered 25/7, 2013 at 15:48 Comment(2)
Doesn't work. I get "backupstorefolder: command not found" from bash where "backupstorefolder" is the name of a variable.Horlacher
This helps syntax highlighting quite a bit, and removes some human ambiguity.Clearway
D
51
foo="Hello "
foo="$foo World"

     

Dextrocular answered 15/11, 2010 at 5:44 Comment(3)
This is the most useful answer for shell scripting. I have found myself the last 30 minutes because I had a space before and after the equal sign!!Krill
foo="${foo}World"Fossick
@Fossick surely I'd rather use brackets to encapsulate var's name. Highly recommendedUniliteral
D
44

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.

See also:

Dupont answered 6/12, 2017 at 4:4 Comment(1)
If you are concerned about performance, see an analysis in my answer https://mcmap.net/q/40378/-how-to-concatenate-string-variables-in-bashOxygen
C
38

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
Cadastre answered 7/3, 2014 at 16:43 Comment(2)
...hence ${a}\ World produces Hello WorldBrag
This surprises me; I would have expected c=$a$b here to do the same thing as c=$a World (which would try to run World as a command). I guess that means the assignment is parsed before the variables are expanded..Marvellamarvellous
F
32
$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop
Foam answered 15/11, 2010 at 5:42 Comment(0)
S
22

Yet another approach...

> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.

...and yet yet another one.

> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
Secern answered 18/3, 2013 at 8:24 Comment(2)
That's what I did, and I found it so much simple and straight-forward than the other answers. Is there a reason nobody on the most voted answers pointed this option out?Wellspring
@Wellspring The fact the strings do not match those used in the OP question might be a good reason.Reprehend
T
20

If you want to append something like an underscore, use escape (\)

FILEPATH=/opt/myfile

This does not work:

echo $FILEPATH_$DATEX

This works fine:

echo $FILEPATH\\_$DATEX
Tamarisk answered 20/9, 2013 at 19:15 Comment(3)
Or alternatively, ${FILEPATH}_$DATEX. Here {} are used to indicate the boundaries of the variable name. This is appropariate because the underscore is a legal character in variable names, so in your snippet bash actually tries to resolve FILEPATH_, not just $FILEPATHAubervilliers
for me I had one variable i.e. $var1 and constant next to this, so echo $var1_costant_traling_part works for meSelway
I guess one needs only one backlash for escaping: echo $a\_$b would do. As hinted in the comment of Nik O'Lai the underscore is a regular character. The handling of white spaces is much more sensitive for strings, echo and concatenation --- one can use \ and read this thread thoroughly as this issue comes back now and then.Brag
E
16

The simplest way with quotation marks:

B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
Eutherian answered 21/12, 2016 at 15:23 Comment(2)
Too many quotation marks, IMHO. var=$B$b"a"; echo Hello\ $var would do, I believeBrag
I suggest to use all of the quotation marks, cause if you put it everywhere you cannot miss, you dont have to think.Eutherian
B
15

Even if the += operator is now permitted, it has been introduced in Bash 3.1 in 2004.

Any script using this operator on older Bash versions will fail with a "command not found" error if you are lucky, or a "syntax error near unexpected token".

For those who cares about backward compatibility, stick with the older standard Bash concatenation methods, like those mentioned in the chosen answer:

foo="Hello"
foo="$foo World"
echo $foo
> Hello World
Barye answered 4/11, 2014 at 19:57 Comment(1)
Thanks for pointing this out, I was just searching for which version is require for this to work.Aught
O
15

Variables and arrays (indexed or associative*) in Bash are always strings by default, but you can use flags to the declare builtin, to give them attributes like "integer" (-i) or "reference"** (-n), which change the way they behave.

Bash arithmetic accepts ASCII/string numbers for input, so there are few reasons to actually use the integer attribute.

Also, variable values can't contain ASCII NULL (i.e., 8 bit zero), because regular null terminated C strings are used to implement them.

* Ie one or more key + value pairs.
** Reference variables expand to the value of another variable, whose label is assigned to the reference variable

Append a string:

$ foo=Hello
$ foo+=' world!'
$ echo "$foo"

Hello world!

$ num=3
$ num+=4
echo "$num"

34 # Appended string (not a sum)

One of the few reasons to use the integer attribute, is that it changes the behaviour of the += assignment operator:

$ declare -i num=3
$ num+=4
echo "$num"

7 # Sum

Note that this doesn't work for -=, /=, etc. unless you do it inside arithmetic ((( )) and $(( ))), where numbers are already treated the same with or without the integer attribute. See the section "arithmetic evaluation" of man bash for a full list of those operators, which are the same as for C.

The += assignment operator can also be used to append new elements to an indexed array (AKA "list"):

$ foo=(one)
$ foo+=(two)
$ printf 'Separate element: %s\n' "${foo[@]}"

Separate element: one
Separate element: two

Another common way to do this is to use a counter:

$ foo[c++]=one
$ foo[c++]=two

POSIX shells do not use the += assignment operator to append strings, so you have to do it like this:

$ foo=Hello
$ foo="$foo world!"
$ echo "$foo"

Hello world!

This is fine in Bash too, so it could be considered a more portable syntax.

Outlying answered 10/6, 2021 at 12:16 Comment(0)
T
14

You can concatenate without the quotes. Here is an example:

$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3

This last statement would print "OpenSystems" (without quotes).

This is an example of a Bash script:

v1=hello
v2=world
v3="$v1       $v2"
echo $v3            # Output: hello world
echo "$v3"          # Output: hello       world
Therapist answered 15/11, 2010 at 7:40 Comment(1)
The syntax of the first block is confusing. What do these $ signs mean?Brag
T
14

I prefer to use curly brackets ${} for expanding variable in string:

foo="Hello"
foo="${foo} World"
echo $foo
> Hello World

Curly brackets will fit to Continuous string usage:

foo="Hello"
foo="${foo}World"
echo $foo
> HelloWorld

Otherwise using foo = "$fooWorld" will not work.

Titograd answered 14/6, 2017 at 5:35 Comment(0)
M
13

Despite of the special operator, +=, for concatenation, there is a simpler way to go:

foo='Hello'
foo=$foo' World'
echo $foo

Double quotes take an extra calculation time for interpretation of variables inside. Avoid it if possible.

Mclaren answered 18/9, 2019 at 6:28 Comment(0)
C
8

Safer way:

a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD

Strings containing spaces can become part of command, use "$XXX" and "${XXX}" to avoid these errors.

Plus take a look at other answer about +=

Corabella answered 26/2, 2014 at 23:39 Comment(1)
The point of the strings with a space that are read as a command shows up at the point of definition. So d=DD DD would give DD: command not found --- note that is the last DD, rather d that is not found. If all operands are properly formatted and already contain the required spaces, you can simply concatenate with s=${a}${b}${c}${d}; echo $s, with less quote marks. Also you could use \ (escaped whitespace) to avoid these issues --- d=echo\ echo will not launch any echo invocation, whereas d=echo echo will.Brag
A
8

There's one particular case where you should take care:

user=daniel
cat > output.file << EOF
"$user"san
EOF

Will output "daniel"san, and not danielsan, as you might have wanted. In this case you should do instead:

user=daniel
cat > output.file << EOF
${user}san
EOF
Alfreda answered 28/10, 2015 at 17:35 Comment(0)
F
7

If what you are trying to do is to split a string into several lines, you can use a backslash:

$ a="hello\
> world"
$ echo $a
helloworld

With one space in between:

$ a="hello \
> world"
$ echo $a
hello world

This one also adds only one space in between:

$ a="hello \
>      world"
$ echo $a
hello world
Flavine answered 3/4, 2012 at 23:22 Comment(1)
I'm afraid this is not what was meantTaenia
O
7

There are voiced concerns about performance, but no data is offered. Let me suggest a simple test.

(NOTE: date on macOS does not offer nanoseconds, so this must be done on Linux.)

I have created append_test.sh on GitHub with the contents:

#!/bin/bash -e

output(){
    ptime=$ctime;
    ctime=$(date +%s.%N);
    delta=$(bc <<<"$ctime - $ptime");
    printf "%2s. %16s chars  time: %s  delta: %s\n" $n "$(bc <<<"10*(2^$n)")" $ctime $delta;
}

method1(){
    echo 'Method: a="$a$a"'
    for n in {1..32}; do a="$a$a"; output; done
}

method2(){
    echo 'Method: a+="$a"'
    for n in {1..32}; do a+="$a";  output; done
}

ctime=0; a="0123456789"; time method$1

Test 1:

$ ./append_test.sh 1
Method: a="$a$a"
 1.               20 chars  time: 1513640431.861671143  delta: 1513640431.861671143
 2.               40 chars  time: 1513640431.865036344  delta: .003365201
 3.               80 chars  time: 1513640431.868200952  delta: .003164608
 4.              160 chars  time: 1513640431.871273553  delta: .003072601
 5.              320 chars  time: 1513640431.874358253  delta: .003084700
 6.              640 chars  time: 1513640431.877454625  delta: .003096372
 7.             1280 chars  time: 1513640431.880551786  delta: .003097161
 8.             2560 chars  time: 1513640431.883652169  delta: .003100383
 9.             5120 chars  time: 1513640431.886777451  delta: .003125282
10.            10240 chars  time: 1513640431.890066444  delta: .003288993
11.            20480 chars  time: 1513640431.893488326  delta: .003421882
12.            40960 chars  time: 1513640431.897273327  delta: .003785001
13.            81920 chars  time: 1513640431.901740563  delta: .004467236
14.           163840 chars  time: 1513640431.907592388  delta: .005851825
15.           327680 chars  time: 1513640431.916233664  delta: .008641276
16.           655360 chars  time: 1513640431.930577599  delta: .014343935
17.          1310720 chars  time: 1513640431.954343112  delta: .023765513
18.          2621440 chars  time: 1513640431.999438581  delta: .045095469
19.          5242880 chars  time: 1513640432.086792464  delta: .087353883
20.         10485760 chars  time: 1513640432.278492932  delta: .191700468
21.         20971520 chars  time: 1513640432.672274631  delta: .393781699
22.         41943040 chars  time: 1513640433.456406517  delta: .784131886
23.         83886080 chars  time: 1513640435.012385162  delta: 1.555978645
24.        167772160 chars  time: 1513640438.103865613  delta: 3.091480451
25.        335544320 chars  time: 1513640444.267009677  delta: 6.163144064
./append_test.sh: fork: Cannot allocate memory

Test 2:

$ ./append_test.sh 2
Method: a+="$a"
 1.               20 chars  time: 1513640473.460480052  delta: 1513640473.460480052
 2.               40 chars  time: 1513640473.463738638  delta: .003258586
 3.               80 chars  time: 1513640473.466868613  delta: .003129975
 4.              160 chars  time: 1513640473.469948300  delta: .003079687
 5.              320 chars  time: 1513640473.473001255  delta: .003052955
 6.              640 chars  time: 1513640473.476086165  delta: .003084910
 7.             1280 chars  time: 1513640473.479196664  delta: .003110499
 8.             2560 chars  time: 1513640473.482355769  delta: .003159105
 9.             5120 chars  time: 1513640473.485495401  delta: .003139632
10.            10240 chars  time: 1513640473.488655040  delta: .003159639
11.            20480 chars  time: 1513640473.491946159  delta: .003291119
12.            40960 chars  time: 1513640473.495354094  delta: .003407935
13.            81920 chars  time: 1513640473.499138230  delta: .003784136
14.           163840 chars  time: 1513640473.503646917  delta: .004508687
15.           327680 chars  time: 1513640473.509647651  delta: .006000734
16.           655360 chars  time: 1513640473.518517787  delta: .008870136
17.          1310720 chars  time: 1513640473.533228130  delta: .014710343
18.          2621440 chars  time: 1513640473.560111613  delta: .026883483
19.          5242880 chars  time: 1513640473.606959569  delta: .046847956
20.         10485760 chars  time: 1513640473.699051712  delta: .092092143
21.         20971520 chars  time: 1513640473.898097661  delta: .199045949
22.         41943040 chars  time: 1513640474.299620758  delta: .401523097
23.         83886080 chars  time: 1513640475.092311556  delta: .792690798
24.        167772160 chars  time: 1513640476.660698221  delta: 1.568386665
25.        335544320 chars  time: 1513640479.776806227  delta: 3.116108006
./append_test.sh: fork: Cannot allocate memory

The errors indicate that my Bash got up to 335.54432 MB before it crashed. You could change the code from doubling the data to appending a constant to get a more granular graph and failure point. But I think this should give you enough information to decide whether you care. Personally, below 100 MB I don't. Your mileage may vary.

Oxygen answered 18/12, 2017 at 23:56 Comment(1)
Interesting! Consider: join <(LANG=C bash -c 'a="a" c=1 last=${EPOCHREALTIME//.};while :;do a+=$a;now=${EPOCHREALTIME//.};echo $((c++)) ${#a} $((now-last));last=$now;done') <(LANG=C bash -c 'a="a" c=1 last=${EPOCHREALTIME//.};while :;do a=$a$a;now=${EPOCHREALTIME//.};echo $((c++)) ${#a} $((now-last));last=$now;done')|sed -ue '1icnt strlen a+=$a a=$a$a' -e 's/^\([0-9]\+\) \([0-9]\+\) \([0-9]\+\) \2/\1 \2 \3/' | xargs printf "%4s %11s %9s %9s\n" (Try this on not productive host!! ;)Closestool
A
6
a="Hello,"
a=$a" World!"
echo $a

This is how you concatenate two strings.

Anamorphic answered 5/3, 2019 at 19:35 Comment(1)
This works, but it will sometimes yield unpredictable results because the variable interpolation is not protected. Thus, you cannot rely on this form for all use cases.Lumbering
F
5

If it is as your example of adding " World" to the original string, then it can be:

#!/bin/bash

foo="Hello"
foo=$foo" World"
echo $foo

The output:

Hello World
Form answered 24/4, 2015 at 5:7 Comment(0)
I
5
var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3
Irishirishism answered 7/2, 2017 at 8:50 Comment(1)
Also var3=$var1\ $var2 has the same effectBrag
C
5

I wanted to build a string from a list. Couldn't find an answer for that so I post it here. Here is what I did:

list=(1 2 3 4 5)
string=''

for elm in "${list[@]}"; do
    string="${string} ${elm}"
done

echo ${string}

and then I get the following output:

1 2 3 4 5
Cracy answered 21/10, 2018 at 10:6 Comment(0)
R
3

Note that this won't work

foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar

as it seems to drop $foo and leaves you with:

PREFIX_WORLD

but this will work:

foobar=PREFIX_"$foo"_"$bar"

and leave you with the correct output:

PREFIX_HELLO_WORLD

Reiterate answered 30/12, 2013 at 20:23 Comment(1)
this happens because the underscore is the valid character in variable names, so bash sees foo_ as a variable. When it is necessary to tell bash the exact var name boundaries, the curly braces can be used: PREFIX_${foo}_$barAubervilliers
V
2

Here is the one through AWK:

$ foo="Hello"
$ foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
$ echo $foo
Hello World
Visage answered 24/8, 2014 at 11:9 Comment(1)
Nice, But I think I could obtain more precision by using Python !Favin
G
1

I do it this way when convenient: Use an inline command!

echo "The current time is `date`"
echo "Current User: `echo $USER`"
Gimble answered 10/1, 2014 at 0:26 Comment(1)
On 1st line, you could drop a fork by using: date "+The current time is %a %b %d %Y +%T", instead of echo ...$(date). Under recent bash, you could write: printf "The current time is %(%a %b %d %Y +%T)T\n" -1 .Closestool
L
0

In my opinion, the simplest way to concatenate two strings is to write a function that does it for you, then use that function.

function concat ()
{
    prefix=$1
    suffix=$2

    echo "${prefix}${suffix}"
}

foo="Super"
bar="man"

concat $foo $bar   # Superman

alien=$(concat $foo $bar)

echo $alien        # Superman
Lumbering answered 9/7, 2019 at 4:8 Comment(0)
M
0

There's also the possibility to use named references in Bash 4.x, to add arbitrary strings to the referenced string (delimited by a referenced separator each):

delcare str='S1'
declare separator=','

# Appends to str ref #1, separated by sep ref #2
app_str() {
    local -n str="$1"
    local -n sep="$2"
    local -a appends=("${@:3}")
    local -i appsLen=${#appends[@]}
    local -i i
    # If any appends, add 1st sep to referenced str
    if [[ $appsLen -gt 0 ]]; then
        str+="${sep}"   
    fi
    for appStr in "${appends[@]}"; do
        str+="$appStr"
        if [[ $((++i)) -lt $appsLen ]]; then
            str+="${sep}"
        fi
    done
}

Use it like so:

app_str str separator 'S2' 'S3' 'S4'
echo -e "$str"

Another way to append (and separate) with `printf``:

declare separator=','
declare testStr='STR1'
declare -a testArr=(STR2 STR3 STR4)
testStr="$testStr"$(printf "$separator%s" "${testArr[@]}")

echo -e "$testStr"
Ministerial answered 20/3 at 15:36 Comment(0)
C
-1

I kind of like making a quick function.

#! /bin/sh -f
function combo() {
    echo $@
}

echo $(combo 'foo''bar')

Yet another way to skin a cat. This time with functions :D

Continuo answered 8/9, 2014 at 7:44 Comment(1)
Calling a function, that too in a subshell, is too much an overkill for a simple concat.Dupont

© 2022 - 2024 — McMap. All rights reserved.