在PHP中,字符串按如下方式连接在一起:
$foo = "Hello";
$foo .= " World";
在这里,$foo变成了“Hello World”。
这是如何在Bash中实现的?
在PHP中,字符串按如下方式连接在一起:
$foo = "Hello";
$foo .= " World";
在这里,$foo变成了“Hello World”。
这是如何在Bash中实现的?
当前回答
默认情况下,Bash中的变量和数组(索引或关联*)始终是字符串,但可以在声明内置函数中使用标志,为它们提供“integer”(-i)或“reference”**(-n)等属性,从而改变它们的行为方式。
Bash算术接受ASCII/字符串数字作为输入,因此实际使用integer属性的原因很少。
此外,变量值不能包含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
请注意,这不适用于-=、/=等,除非在算术((())和$(()()))中执行,在算术中,使用或不使用整数属性时,数字已被视为相同。有关这些运算符的完整列表,请参见manbash的“算术求值”一节,这些运算符与C相同。
+=赋值运算符也可用于将新元素附加到索引数组(AKA“列表”):
$ 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中也很好,因此它可以被认为是一种更可移植的语法。
其他回答
在我看来,连接两个字符串的最简单方法是编写一个函数,然后使用该函数。
function concat ()
{
prefix=$1
suffix=$2
echo "${prefix}${suffix}"
}
foo="Super"
bar="man"
concat $foo $bar # Superman
alien=$(concat $foo $bar)
echo $alien # Superman
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
通常,要连接两个变量,只需将它们一个接一个地写入即可:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
这里是对大多数答案的简要总结。
假设我们有两个变量,$1设置为“1”:
set one two
a=hello
b=world
下表说明了我们可以组合a和b的值来创建新变量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变量名中有效的第一个字符(即字母或下划线)开头。
另请参见:
BashFAQ/013-如何连接两个变量?我们什么时候需要在外壳变量周围使用大括号?
var1='hello'
var2='world'
var3=$var1" "$var2
echo $var3
先猛击
由于这个问题特别适用于Bash,我的第一部分回答将提出不同的正确做法:
+=:附加到变量
语法+=可以以不同的方式使用:
附加到字符串var+=。。。
(因为我很节俭,我只使用两个变量foo和a,然后在整个答案中重复使用相同的变量。;-)
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
注意,括号之间有一个空格分隔的数组。如果要在数组中存储包含空格的字符串,则必须将它们括起来:
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
注意:使用双引号可能有助于处理包含空格、制表符和/或换行符的字符串
printf -v foo "%s World" "$foo"
立即启动Shell
在POSIX shell下,不能使用bashms,因此没有内置printf。
大体上
但你可以简单地做到:
foo="Hello"
foo="$foo World"
echo $foo
Hello World
格式化,使用分叉打印
如果要使用更复杂的构造,必须使用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