How to concatenate string variables in Bash
在PHP中,字符串按如下方式连接在一起:
1 2 | $foo ="Hello"; $foo .=" World"; |
在这里,
这是如何在bash中完成的?
1 2 3 4 | foo="Hello" foo="$foo World" echo $foo > Hello World |
一般来说,要连接两个变量,您可以一个接一个地编写它们:
1 2 3 4 5 | a='hello' b='world' c="$a$b" echo $c > helloworld |
bash还支持
1 2 3 4 | $ A="X Y" $ A+=" Z" $ echo"$A" X Y Z |
猛击第一
因为这个问题专门代表bash,所以我的第一部分答案将给出正确执行此操作的不同方法:
语法
(因为我节俭,我只使用两个变量
1 2 3 4 | a=2 a+=4 echo $a 24 |
使用堆栈溢出问题语法,
1 2 3 4 | foo="Hello" foo+=" World" echo $foo Hello World |
工作很好!
附加到整数EDOCX1[8]变量
1 2 3 4 5 | echo $a 24 ((a+=12)) echo $a 36 |
追加到数组EDOCX1[10]
我们的
1 2 3 4 5 6 7 8 9 10 11 | echo ${a[@]} 36 a+=(18) echo ${a[@]} 36 18 echo ${a[0]} 36 echo ${a[1]} 18 |
注意在括号之间有一个空格分隔的数组。如果要在数组中存储包含空格的字符串,则必须将它们括起来:
1 2 | a+=(one word"hello world!" ) bash: !": event not found |
隐马尔可夫模型。。这不是一个bug,而是一个特性…为了防止bash尝试开发
1 2 3 4 5 | 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!")' |
1 2 | echo ${a[@]} 36 18 one word hello world! hello world! hello world! |
这个数组中有七个字符串。因此,我们可以构建一个格式字符串,其中正好包含七个位置参数:
1 2 3 | printf -v a"%s./.%s...'%s' '%s', '%s'=='%s'=='%s'""${a[@]}" echo $a 36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!' |
或者我们可以使用一个参数格式字符串,该字符串将重复提交的参数…
注意,我们的
1 2 3 4 | 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下,当您在不指定索引的情况下访问变量名时,总是只处理第一个元素!
因此,要检索七个字段数组,只需重新设置第一个元素:
1 2 3 4 | 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!")' |
一个参数格式字符串,多个参数传递给:
1 2 3 4 5 6 7 8 9 10 | printf -v a[0] '<%s> '"${a[@]}" echo"$a" <36> <18> <one> <word> <hello world!> <hello world!> <hello world!> |
使用堆栈溢出问题语法:
1 2 3 4 | foo="Hello" printf -v foo"%s World" $foo echo $foo Hello World |
注:使用双引号可能有助于操作包含
1 | printf -v foo"%s World""$foo" |
贝壳现在
在posix shell下,不能使用bashims,因此没有内置的
但你可以简单地做到:
1 2 3 4 | foo="Hello" foo="$foo World" echo $foo Hello World |
格式化,使用分叉
如果要使用更复杂的结构,则必须使用fork(新的子进程,该进程生成作业并通过
1 2 3 4 | foo="Hello" foo=$(printf"%s World""$foo") echo $foo Hello World |
历史上,您可以使用backticks来检索fork的结果:
1 2 3 4 | foo="Hello" foo=`printf"%s World""$foo"` echo $foo Hello World |
但这并不容易筑巢:
1 2 3 4 | foo="Today is:" foo=$(printf"%s %s""$foo""$(date)") echo $foo Today is: Sun Aug 4 11:58:23 CEST 2013 |
用反勾号,你必须用反斜杠从内部叉子中逃脱:
1 2 3 4 | foo="Today is:" foo=`printf"%s %s""$foo""\`date\`"` echo $foo Today is: Sun Aug 4 11:59:10 CEST 2013 |
您也可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 | $ var="myscript" $ echo $var myscript $ var=${var}.sh $ echo $var myscript.sh |
1 2 3 | bla=hello laber=kthx echo"${bla}ohai${laber}bye" |
意志输出
1 | helloohaikthxbye |
当
1 2 | foo="Hello" foo="$foo World" |
&(二)
我解决这个问题的方法只是
1 | $a$b |
例如,
1 2 3 4 | a="Hello" b=" World" c=$a$b echo"$c" |
产生
1 | Hello World |
例如,如果您试图将一个字符串与另一个字符串连接起来,
1 2 | a="Hello" c="$a World" |
那么,
1 | Hello World |
有额外的空间。
1 | $aWorld |
不起作用,你可以想象,但是
1 | ${a}World |
生产
1 | HelloWorld |
1 2 3 4 5 6 7 | $ a=hip $ b=hop $ ab=$a$b $ echo $ab hiphop $ echo $a$b hiphop |
如果要附加下划线之类的内容,请使用转义()
1 | FILEPATH=/opt/myfile |
这不起作用:
1 | echo $FILEPATH_$DATEX |
这很好用:
1 | echo $FILEPATH\\_$DATEX |
以下是对大多数答案的简要总结。
假设我们有两个变量:
1 2 | a=hello b=world |
下表解释了不同的上下文,我们可以将
1 2 3 4 5 6 7 8 | Context | Expression | Result (value of c) --------------------------------------+-----------------------+--------------------- Two variables | c=$a$b | helloworld 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行所示)。
参见:
- bashfaq/013-如何连接两个变量?
- 我们什么时候需要在shell变量周围使用大括号?
另一种方法…
1 2 3 4 | > H="Hello" > U="$H""universe." > echo $U Hello universe. |
…还有另一个。
1 2 3 4 | > H="Hello" > U=$H"universe." > echo $U Hello universe. |
使用引号的最简单方法:
1 2 3 4 | B=Bar b=bar var="$B""$b""a" echo"Hello""$var" |
您可以不带引号地连接。下面是一个例子:
1 2 3 4 | $Variable1 Open $Variable2 Systems $Variable3 $Variable1$Variable2 $echo $Variable3 |
最后一条语句将打印"OpenSystems"(不带引号)。
这是bash脚本的一个示例:
1 2 3 4 5 | v1=hello v2=world v3="$v1 $v2" echo $v3 # Output: hello world echo"$v3" # Output: hello world |
即使现在允许使用+=操作符,2004年bash 3.1中也引入了它。
在旧的bash版本上使用此运算符的任何脚本都将失败,如果幸运的话,将出现"command not found"错误,或者出现"syntax error near unexpected token"。
对于那些关心向后兼容性的人,请坚持使用旧的标准bash连接方法,如所选答案中提到的方法:
1 2 3 4 | foo="Hello" foo="$foo World" echo $foo > Hello World |
我喜欢使用花括号
1 2 3 4 | foo="Hello" foo="${foo} World" echo $foo > Hello World |
大括号将适合连续使用字符串:
1 2 3 4 | foo="Hello" foo="${foo}World" echo $foo > HelloWorld |
否则,使用
如果您要做的是将字符串拆分为多行,则可以使用反斜杠:
1 2 3 4 | $ a="hello\ > world" $ echo $a helloworld |
中间有一个空格:
1 2 3 4 | $ a="hello \ > world" $ echo $a hello world |
这一个只在中间添加了一个空格:
1 2 3 4 | $ a="hello \ > world" $ echo $a hello world |
更安全的方式:
1 2 3 4 5 6 7 | a="AAAAAAAAAAAA" b="BBBBBBBBBBBB" c="CCCCCCCCCCCC" d="DD DD" s="${a}${b}${c}${d}" echo"$s" AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD |
包含空格的字符串可以成为命令的一部分,请使用"$XXX"和"$XXX"避免这些错误。
再看看其他答案+=
有一个特别的情况,你应该注意:
1 2 3 4 | user=daniel cat > output.file << EOF "$user"san EOF |
将输出
1 2 3 4 | user=daniel cat > output.file << EOF ${user}san EOF |
如果是将
1 2 3 4 5 | #!/bin/bash foo="Hello" foo=$foo" World" echo $foo |
输出:
1 | Hello World |
1 2 3 4 | var1='hello' var2='world' var3=$var1""$var2 echo $var3 |
我想从列表中构建一个字符串。找不到答案,所以我把它贴在这里。以下是我所做的:
1 2 3 4 5 6 7 8 | list=(1 2 3 4 5) string='' for elm in"${list[@]}"; do string="${string} ${elm}" done echo ${string} |
然后我得到以下输出:
1 | 1 2 3 4 5 |
注意这不管用
1 2 3 | foo=HELLO bar=WORLD foobar=PREFIX_$foo_$bar |
因为它好像掉了$foo,留给你:
PREFIX_WORLD
但这是可行的:
1 | foobar=PREFIX_"$foo"_"$bar" |
并为您提供正确的输出:
PREFIX_HELLO_WORLD
1 2 3 | a="Hello," a=$a" World!" echo $a |
这是连接两个字符串的方法。
有人对性能表示担忧,但没有提供任何数据。我建议你做一个简单的测试。
(注:MacOS上的
我在Github上创建了append_test.sh,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/bin/bash -e output(){ ptime=$ctime; ctime=$(date +%s.%N); delta=$(bc <<<"$ctime - $ptime"); printf"%2s. %16s chars time: %s delta: %s " $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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | $ ./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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | $ ./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。您可以将代码从加倍数据改为附加常量,以获得更细粒度的图形和故障点。但我认为这应该给你足够的信息来决定你是否在乎。个人而言,低于100兆我不知道。您的里程可能会有所不同。
我在方便的时候这样做:使用一个内联命令!
1 2 | echo"The current time is `date`" echo"Current User: `echo $USER`" |
这是一个通过awk:
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ foo="Hello" $ foo=$(awk -v var=$foo 'BEGIN{print var" World <div class="suo-content">[collapse title=""]<ul><li>很好,但我想我可以通过使用python获得更高的精度!</li></ul>[/collapse]</div><hr> <p> I kind of like making a quick function. </p> [cc lang="bash"]#! /bin/sh -f function combo() { echo $@ } echo $(combo 'foo''bar') |
另一种剥猫皮的方法。这次功能:d
我还不知道PHP,但它在LinuxBash中工作。如果不想将其影响到变量,可以尝试以下操作:
1 2 3 4 5 | read pp; *# Assumes I will affect Hello to pp* pp=$( printf $pp ;printf ' World'; printf '!'); echo $pp; >Hello World! |
您可以放置另一个变量,而不是"hello"或"!"。您也可以连接更多的字符串。
你可以试试下面的方法。当替换发生时,双引号将保留空格。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |