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


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

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

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

如何在Bash中完成?


2102
2017-11-15 05:38


起源


foo="Hello"  foo=$foo" World"  echo $foo      这相当适用于“#!/ bin / sh” - parasrish
如果你想要HelloWorld没有空间怎么办? - Adi


答案:


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

通常,要连接两个变量,您可以一个接一个地编写它们:

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

2852
2017-11-15 05:41



养成放的习惯可能很好 $foo 在双引号内,对于真正重要的时候。 - Cascabel
我们被教导要始终这样做,因为当替换发生时,shell会忽略空格,但双引号将始终保护这些空格。 - Strawberry
你的第一个例子中是否必须有空格?是否有可能做类似的事情 foo="$fooworld"?我不认为...... - nonsensickle
@nonsensickle那会寻找一个名为的变量 fooworld。使用大括号消除歧义,如 foo="${foo}world"... - twalberg
@ JVE999是的,这也有效,虽然在我看来它对代码清晰度来说并不是那么好......但这可能只是我的偏好......还有其他一些方法可以做到 - 重点是确保变量名称与非变量名称部分分开,以便正确分析。 - twalberg


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

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

939
2017-11-15 08:33



这比接受的答案要好得多,谢谢!添加“附加”作为标记,以便更容易找到此问题。 - noamtm
我可以在export关键字中使用此语法吗?例如 export A+="Z" 或许是 A 变量只需要导出一次? - levesque
@levesque:两个:-)。变量只需要导出一次,但是 export A+=Z 工作也相当不错。 - thkala
由于这是一种基础,我认为值得一提的是你永远不应该使用 #!/bin/sh 在使用这种结构的脚本中。 - Score_Under
它是专门的,只有一个正等运算符。也就是说,与Bavascript不同,在Bash中,echo $ A + $ B打印“X Y + Z” - phpguru


Bash第一

由于这个问题专门针对 巴什,我的答案的第一部分将提出不同的方法来做到这一点:

+=:附加到变量

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

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

(因为我节俭,我只会使用两个变量 foo 和 a 然后在整个答案中重复使用相同的内容。 ;-)

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

嗯.. 这不是一个错误,而是一个功能...防止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  内置 命令提供了一种绘制字符串格式的强大方法。因为这是一个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"

壳牌现在

POSIX shell,你无法使用 bash化所以没有 内置  printf

基本上

但你可以这样做:

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

格式化,使用   printf

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

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

从历史上看,你可以使用 反引号 用于检索结果 叉子

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

807
2017-08-04 10:04



该 += 运算符也比快 $a="$a$b" 在我的测试..这是有道理的。 - Matt
这个答案很棒,但我认为它错过了 var=${var}.sh 其他答案的例子,非常有用。 - geneorama
是 bash 唯一的外壳 += 运营商?我想看看它是否足够便携 - dashesy
@dashesy没有。我肯定不是唯一的外壳 += 运营商,但所有这些方式 bash化,所以不便携!即使你在错误的bash版本的情况下遇到特殊的bug! - F. Hauri


你也可以这样做:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh

114
2017-10-28 03:09



虽然没有使用特殊字符或空格,但双引号,引号和大括号都是无用的: var=myscript;var=$var.sh;echo $var 会有相同的效果(这项工作在bash,dash,busybox等下)。 - F. Hauri


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

会输出

helloohaikthxbye

这很有用      $blaohai 导致变量未找到错误。或者如果字符串中有空格或其他特殊字符。 "${foo}" 妥善逃脱你投入的任何东西。


103
2017-07-25 15:48



不起作用。我从bash获得“backupstorefolder:command not found”,其中“backupstorefolder”是变量的名称。 - Zian Choy
这有助于语法突出显示,并消除了一些人为歧义。 - Ray Foss


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


35
2017-11-15 05:44



这是shell脚本最有用的答案。我发现自己是最后30分钟因为我在等号之前和之后都有空位!! - Stefan
富= “$ {} foo的世界” - XXL


我解决问题的方法就是

$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

29
2018-03-07 16:43



因此... ${a}\ World 产生 Hello World - XavierStuvw


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

22
2017-11-15 05:42





又一种方法......

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

......还有一个。

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

18
2018-03-18 08:24



这就是我所做的,我发现它比其他答案简单直接。有没有理由在最多投票的答案中指出这个选项? - quimnuss
@quimnuss字符串与OP问题中使用的字符串不匹配的事实可能是一个很好的理由。 - jlliagre
......还有一个: U=${H}universe..... - XavierStuvw