Answers:
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
通常,要串联两个变量,可以一个接一个地写它们:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
$foo
确实很重要的时期,养成双引号的习惯可能很好。
foo="$fooworld"
吗?我会假设没有...
fooworld
。消除使用括号的歧义,例如foo="${foo}world"
...
Bash还支持+=
以下代码所示的运算符:
$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
export A+="Z"
,也许A
变量只需要导出一次?
export A+=Z
效果也很好。
#!/bin/sh
在使用此构造的脚本中使用。
bash
某些其他更高级的外壳中受支持。它不能在busybox sh
或dash
(/bin/sh
很多发行版上)或某些其他Shell(如/bin/sh
FreeBSD上提供的外壳)下工作。
正如这个问题专门代表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
请注意,在括号之间有一个以空格分隔的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
NOTA:使用双引号可以是用于操作包含字符串有用spaces
,tabulations
和/或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
+=
运营商也比快得多$a="$a$b"
在我的测试中..这是有道理的。
var=${var}.sh
其他答案都缺少该示例,这非常有用。
bash
唯一能与外壳+=
运营商?我想看看它是否具有足够的便携性
+=
操作符的shell ,但是所有这些方式都是bashisms,所以不是可移植的!甚至在bash版本错误的情况下也可能遇到特殊错误!
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}\ World
产生Hello World
c=$a$b
在这里做与c=$a World
(将尝试World
作为命令运行)相同的事情。我想这意味着在扩展变量之前会先解析分配
这是大多数答案在说的简短摘要。
假设我们有两个变量,并且$ 1设置为'one':
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
一些注意事项:
+=
从性能的角度来看,如果以小增量(尤其是在循环中)构造大字符串,则效果更好{}
变量名来消除它们的扩展歧义(如上表中的第2行)。从第3行和第4行可以看出,{}
除非将变量与以一个字符开头的字符串连接在一起,该字符是shell变量名称中有效的第一个字符,即字母或下划线,否则无需这样做。也可以看看:
如果要附加下划线,请使用转义(\)
FILEPATH=/opt/myfile
这并不能正常工作:
echo $FILEPATH_$DATEX
这工作正常:
echo $FILEPATH\\_$DATEX
echo $a\_$b
会的。正如Nik O'Lai的评论所暗示的,下划线是常规字符。对于字符串,回显和串联,空白的处理要敏感得多- \
随着此问题不时出现,人们可以彻底使用和读取此线程。
带引号的最简单方法:
B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
var=$B$b"a"; echo Hello\ $var
我相信会做到的
您可以串联而不使用引号。这是一个例子:
$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
如果你正在尝试做的是分割字符串成几行,你可以用一个反斜杠:
$ a="hello\
> world"
$ echo $a
helloworld
中间有一个空格:
$ a="hello \
> world"
$ echo $a
hello world
这两个之间也仅添加一个空格:
$ a="hello \
> world"
$ echo $a
hello world
更安全的方法:
a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD
包含空格的字符串可以成为命令的一部分,请使用“ $ XXX”和“ $ {XXX}”来避免这些错误。
再看一下关于+ =的其他答案
d=DD DD
,DD: command not found
请注意---是最后一个DD,而不是找不到的d。如果所有操作数的格式正确,并且已经包含必需的空格,则可以简单地将s=${a}${b}${c}${d}; echo $s
,与串联,并使用较少的引号。您也可以使用\
(转义的空格)来避免这些问题--- d=echo\ echo
不会启动任何回声调用d=echo echo
。
a="Hello,"
a=$a" World!"
echo $a
这是连接两个字符串的方式。
人们对性能表示担忧,但是没有提供任何数据。让我建议一个简单的测试。
(注意:date
在macOS上不提供纳秒级,因此必须在Linux上完成。)
我在GitHub上创建了append_test.sh,内容如下:
#!/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。您可以将代码从加倍数据更改为附加常量,以获取更精细的图形和故障点。但是我认为这应该给您足够的信息来决定您是否在乎。就个人而言,我不超过100 MB。你的旅费可能会改变。
join <(LANG=C bash -c 'a="a" c=1 last=${EPOCHREALTIME//.};while :;do a+=$a;now=${EPOCHREALTIME//.};echo $((c++)) ${#a} $((now-last));last=$now;done') <(LANG=C bash -c 'a="a" c=1 last=${EPOCHREALTIME//.};while :;do a=$a$a;now=${EPOCHREALTIME//.};echo $((c++)) ${#a} $((now-last));last=$now;done')|sed -ue '1icnt strlen a+=$a a=$a$a' -e 's/^\([0-9]\+\) \([0-9]\+\) \([0-9]\+\) \2/\1 \2 \3/' | xargs printf "%4s %11s %9s %9s\n"
在
请注意,这行不通
foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar
因为它似乎会丢弃$ foo并留下:
PREFIX_WORLD
但这可以工作:
foobar=PREFIX_"$foo"_"$bar"
并为您提供正确的输出:
PREFIX_HELLO_WORLD
方便时,我这样做:使用内联命令!
echo "The current time is `date`"
echo "Current User: `echo $USER`"
date "+The current time is %a %b %d %Y +%T"
echo ...$(date)
printf "The current time is %(%a %b %d %Y +%T)T\n" -1
我有点喜欢快速功能。
#! /bin/sh -f
function combo() {
echo $@
}
echo $(combo 'foo''bar')
换皮猫的另一种方式。这次带功能:D
我还不了解PHP,但这在Linux Bash中有效。如果您不想将其影响到变量,则可以尝试以下操作:
read pp; *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;
>Hello World!
您可以放置另一个变量,而不是“ Hello”或“!”。您也可以连接更多字符串。
foo="Hello"
foo=$foo" World"
echo $foo
这对于“#!/ bin / sh”