如何在Bash中连接字符串变量

时间:2010-11-15 05:38:35

标签: bash shell syntax concat string-concatenation

在PHP中,字符串连接在一起如下:

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

在这里,$foo成为“Hello World”。

这是如何在Bash中完成的?

32 个答案:

答案 0 :(得分:3312)

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

一般来说,要连接两个变量,你可以一个接一个地写它们:

a='hello'
b='world'
c="$a$b"
echo $c
> helloworld

答案 1 :(得分:1034)

Bash还支持+=运算符,如以下代码所示:

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

答案 2 :(得分:890)

首先打击

由于这个问题专门针对Bash,我的答案的第一部分会提出不同的方法:

+=:附加到变量

语法 += 可能会以不同的方式使用:

追加到字符串var+=...

(因为我节俭,我只会使用两个变量fooa,然后在整个答案中重复使用它。; - )

a=2
a+=4
echo $a
24

使用 Stack Overflow问题语法,

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

工作正常!

附加到整数((var+=...))

变量a是一个字符串,但也是一个整数

echo $a
24
((a+=12))
echo $a
36

追加到数组var+=(...)

我们的a也只是一个元素的数组。

echo ${a[@]}
36

a+=(18)

echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18

请注意,在括号之间,有一个空格分隔的数组。如果要在数组中存储包含空格的字符串,则必须将它们括起来:

a+=(one word "hello world!" )
bash: !": event not found

嗯...... this is not a bug, but a feature ...为防止bash尝试开发!",您可以:

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:使用内置命令重构变量

printf builtin 命令提供了一种绘制字符串格式的强大方法。由于这是Bash 内置,因此可以选择将格式化字符串发送到变量而不是在stdout上打印:

echo ${a[@]}
36 18 one word hello world! hello world! hello world!

此数组中有七个字符串。所以我们可以构建一个包含七个位置参数的格式化字符串:

printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'

或者我们可以使用一个参数格式字符串,这将在提交的参数中重复...

请注意,我们的a仍然是一个数组!只改变了第一个元素!

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!")'

在bash下,当你在不指定索引的情况下访问变量名时,你总是只对第一个元素进行处理!

因此,为了检索我们的七个字段数组,我们只需要重新设置第一个元素:

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!")'

一个参数格式字符串,其中包含许多参数传递给:

printf -v a[0] '<%s>\n' "${a[@]}"
echo "$a"
<36>
<18>
<one>
<word>
<hello world!>
<hello world!>
<hello world!>

使用 Stack Overflow问题语法:

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

Nota:使用双引号可能对操作包含spacestabulations和/或newlines

的字符串很有用
printf -v foo "%s World" "$foo"

Shell现在

POSIX shell下,您无法使用 bashisms ,因此没有内置 printf

基本上

但你可以这样做:

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

使用分叉 printf

进行格式化

如果你想使用更复杂的结构,你必须使用 fork (创建作业并通过stdout返回结果的新子进程):

foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World

从历史上看,您可以使用反引号来检索 fork 的结果:

foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World

嵌套

并不容易
foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013

使用反引号,你必须使用反斜杠来逃避内部分叉:

foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013

答案 3 :(得分:124)

您也可以这样做:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh

答案 4 :(得分:115)

bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"

将输出

helloohaikthxbye

这很有用     $blaohai 导致变量未找到错误。或者如果字符串中有空格或其他特殊字符。 "${foo}"正确地逃避了你投入的任何事情。

答案 5 :(得分:42)

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

答案 6 :(得分:32)

我解决问题的方法就是

$a$b

例如,

a="Hello"
b=" World"
c=$a$b
echo "$c"

产生

Hello World

如果您尝试将字符串与另一个字符串连接起来,例如

a="Hello"
c="$a World"

然后echo "$c"将产生

Hello World

有一个额外的空间。

$aWorld

无法正常工作,但是

${a}World

产生

HelloWorld

答案 7 :(得分:27)

$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop

答案 8 :(得分:20)

以下是大多数答案所讨论的简要摘要。

我们假设我们有两个变量,$ 1设置为&#39;一个&#39;:

set one two
a=hello
b=world

下表说明了我们可以将ab的值组合在一起以创建新变量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

一些注意事项:

  • 用双引号括起作业的RHS通常是一种很好的做法,尽管在许多情况下它是非常可选的
  • 如果以较小的增量构建一个大字符串,
  • +=从性能的角度来看会更好,尤其是在循环中
  • 在变量名称周围使用{}来消除其扩展的歧义(如上表中的第2行)。如第3行和第4行所示,除非变量与字符串连接,否则不需要{},该字符串以shell变量名中有效的第一个字符开头,即字母或下划线。 / LI>

另见:

答案 9 :(得分:20)

如果要附加下划线之类的内容,请使用escape(\)

FILEPATH=/opt/myfile

工作:

echo $FILEPATH_$DATEX

这很好用:

echo $FILEPATH\\_$DATEX

答案 10 :(得分:19)

又一种方法......

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

......还有一个。

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

答案 11 :(得分:15)

您可以在没有引号的情况下连接。这是一个例子:

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

最后一句话将打印“OpenSystems”(没有引号)。

这是Bash脚本的一个示例:

v1=hello
v2=world
v3="$v1       $v2"
echo $v3            # Output: hello world
echo "$v3"          # Output: hello       world

答案 12 :(得分:15)

引号最简单的方法:

B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"

答案 13 :(得分:14)

即使现在允许+ =运算符,它也已在2004年的 Bash 3.1 中引入。

在较旧的Bash版本上使用此运算符的任何脚本都将失败,如果您幸运,则会出现“未找到命令”错误,或“意外令牌附近的语法错误”。

对于那些关心向后兼容性的人,请坚持使用旧的标准Bash级联方法,如所选答案中提到的那样:

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

答案 14 :(得分:13)

我更喜欢使用大括号${}来扩展字符串中的变量:

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

圆括号适合连续字符串用法:

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

否则使用foo = "$fooWorld"将无效。

答案 15 :(得分:7)

更安全的方式:

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

包含空格的字符串可以成为命令的一部分,使用“$ XXX”和“$ {XXX}”来避免这些错误。

另外,请看一下 + =

的其他答案

答案 16 :(得分:7)

如果你要做的是将拆分一个字符串分成几行,你可以使用反斜杠:

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

中间有一个空格:

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

这个也只增加了一个空格:

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

答案 17 :(得分:6)

您应该注意的一个特殊情况:

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

将输出"daniel"san,而不是danielsan,就像您可能想要的那样。 在这种情况下,你应该做:

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

答案 18 :(得分:5)

如果它是将" World"添加到原始字符串的示例,那么它可以是:

#!/bin/bash

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

输出:

Hello World

答案 19 :(得分:5)

var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3

答案 20 :(得分:4)

a="Hello,"
a=$a" World!"
echo $a

这是连接两个字符串的方式。

答案 21 :(得分:4)

我想从列表中构建一个字符串。找不到答案,所以我在这里发布。这是我所做的:

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

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

echo ${string}

然后我得到以下输出:

1 2 3 4 5

答案 22 :(得分:4)

有人对性能表示担忧,但没有提供数据。让我建议一个简单的测试。

(注意:macOS上的date不提供纳秒,因此必须在Linux上完成。)

我创建了append_test.sh on GitHub,内容为:

#!/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

测试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

测试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

错误表明我的Bash在崩溃之前已经达到 335.54432 MB 。您可以将the code更改为将数据加倍,以附加常量以获得更精细的图形和故障点。但我认为这应该给你足够的信息来决定你是否关心。就个人而言,低于100 MB,我没有。您的里程可能会有所不同。

答案 23 :(得分:3)

请注意,这不起作用

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

因为它似乎放弃了$ foo而离开了你:

  

PREFIX_WORLD

但这会奏效:

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

并留下正确的输出:

  

PREFIX_HELLO_WORLD

答案 24 :(得分:1)

以下是AWK

之一
$ foo="Hello"
$ foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
$ echo $foo
Hello World

答案 25 :(得分:1)

尽管使用特殊运算符+=进行串联,但还有一种更简单的方法:

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

双引号会花费额外的计算时间来解释内部变量,请尽可能避免。

答案 26 :(得分:1)

我方便的时候这样做:使用内联命令!

echo "The current time is `date`"
echo "Current User: `echo $USER`"

答案 27 :(得分:0)

我认为,连接两个字符串的最简单方法是编写一个为您执行此操作的函数,然后使用该函数。

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

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

foo="Super"
bar="man"

concat $foo $bar   # Superman

alien=$(concat $foo $bar)

echo $alien        # Superman

答案 28 :(得分:0)

bash 中的变量和数组(索引或关联*)在默认情况下始终是字符串,但您可以使用 declare 内置的标志,为它们提供诸如“整数”(-i)或“引用”** (-n),这会改变它们的行为方式。

Bash 算法接受 ASCII/字符串数字作为输入,因此几乎没有理由实际使用整数属性。

此外,变量值不能包含 ASCII NULL(即 8 位零),因为使用常规的空终止 C 字符串来实现它们。

* 即一个或多个键+值对。
** 引用变量扩展为另一个变量的值,其标签分配给引用变量

附加一个字符串:

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

$ num=3
$ num+=4
echo "$num"
34 # Appended string (not a sum)

使用整数属性的少数原因之一是它改变了 += 赋值运算符的行为:

$ declare -i num=3
$ num+=4
echo "$num"
7 # Sum

请注意,这不适用于 -=/= 等,除非您在算术((( ))$(( )))中执行此操作,其中数字已被处理有或没有整数属性都一样。有关这些运算符的完整列表,请参阅 man bash 的“算术评估”部分,这些运算符与 C 相同。

+= 赋值运算符还可用于将新元素附加到索引数组(又名“列表”):

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

另一种常见的方法是使用计数器:

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

POSIX shell使用 += 赋值运算符来附加字符串,所以你必须这样做:

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

这在 bash 中也很好,因此可以认为它是一种更可移植的语法。

答案 29 :(得分:-1)

我还不了解PHP,但这适用于Linux Bash。如果您不想将其影响到变量,可以试试这个:

read pp;  *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;

>Hello World!

您可以放置​​另一个变量而不是&#39; Hello&#39;或者&#39;!&#39;。你也可以连接更多的字符串。

答案 30 :(得分:-1)

我有点想做一个快速的功能。

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

echo $(combo 'foo''bar')

另一种给猫皮肤的方法。这次有功能:D

答案 31 :(得分:-4)

您可以尝试以下方式。当替换发生时,双引号将保留空格。

var1="Ram "    
var2="Lakshmana" 
echo $var1$var2
or 
echo var1+=$var2 "bash support += operation.

bcsmc2rtese001 [/tmp]$ var1="Ram "  
bcsmc2rtese001 [/tmp]$ var2="Lakshmana"  
bcsmc2rtese001 [/tmp]$ echo $var1$var2  
Ram Lakshmana  

bcsmc2rtese001 [/tmp]$ var1+=$var2  
bcsmc2rtese001 [/tmp]$ echo $var1  
Ram Lakshmana