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

在 PHP 中,字符串按以下方式串联在一起:

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

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

如何在 Bash 中完成?

答案

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

通常,要串联两个变量,可以一个接一个地写它们:

a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World

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

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

重击第一

正如这个问题专门代表Bash 一样 ,我的答案的第一部分将提出正确执行此操作的不同方法:

+= :附加到变量

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

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

(因为我很节俭,所以我只会使用两个变量fooa ,然后在整个答案中重复使用相同的变量。

a=2
a+=4
echo $a
24

使用堆栈溢出问题语法,

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

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

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

嗯.. 这不是一个 bug,而是一个功能 ... 为了防止 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!>

使用堆栈溢出问题语法:

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

注意:使用双引号可能对处理包含spacestabulations和 / 或newlines字符串很有用

printf -v foo "%s World" "$foo"

现在壳

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

你也可以这样做:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

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

将输出

helloohaikthxbye

$blaohai导致变量未找到错误时,这很有用。或者,如果字符串中包含空格或其他特殊字符。 "${foo}"正确地转义了您放入其中的所有内容。

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

     

我解决问题的方法就是

$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
$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop

这是大多数答案在说的简短摘要。

假设我们有两个变量,并且 $ 1 设置为'one':

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 变量名称中有效的第一个字符(即字母或下划线),否则不需要{}

也可以看看:

还有另一种方法...

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

... 还有一个

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