답변:
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
많은 배포판에 있음) 또는 /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
괄호 사이에는 공백으로 구분 된 배열이 있습니다. 배열에 공백이 포함 된 문자열을 저장하려면 공백을 묶어야합니다.
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!
이 배열 에는 7 개의 문자열 이 있습니다. 따라서 정확히 7 개의 위치 인수를 포함하는 형식화 된 문자열을 작성할 수 있습니다.
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에서 index를 지정하지 않고 변수 이름에 액세스하면 항상 첫 번째 요소 만 처리합니다!
따라서 7 개의 필드 배열을 검색하려면 첫 번째 요소 만 재설정하면됩니다.
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
참고 : 큰 따옴표를 사용하면 spaces
, tabulations
및 / 또는 포함 된 문자열을 조작하는 데 유용 할 수 있습니다newlines
printf -v foo "%s World" "$foo"
에서 POSIX 쉘, 당신은 사용할 수없는 bashisms를 , 그래서이없는 내장은 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
+=
운영자는 것보다 훨씬 빠르기도 $a="$a$b"
의미가 어떤 .. 내 시험한다.
var=${var}.sh
다른 답변 의 예가 누락 된 것 같습니다 . 매우 유용합니다.
bash
있는 유일한 쉘 +=
입니까? 나는 그것이 충분히 휴대용인지 확인하고 싶다
+=
연산자가 있는 유일한 쉘은 아니지만이 모든 방법은 bashisms 이므로 휴대용이 아닙니다! bash 버전이 잘못된 경우에도 특별한 버그가 발생할 수 있습니다!
당신도 이것을 할 수 있습니다 :
$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh
var=myscript;var=$var.sh;echo $var
이 효과는 bash, dash, busybox 및 기타에서 동일합니다.
echo $var2
하지 않습니다 . 예 : 생산하지 않음myscript2
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"
출력
helloohaikthxbye
$blaohai
변수를 찾을 수 없음 오류가 발생할 때 유용합니다
. 또는 문자열에 공백이나 다른 특수 문자가있는 경우. "${foo}"
당신이 넣은 모든 것을 올바르게 탈출합니다.
문제를 해결하는 방법은
$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 행에서 볼 수 있듯이 {}
변수가 쉘 변수 이름의 유효한 첫 번째 문자 인 알파벳 또는 밑줄 인 문자로 시작하는 문자열과 연결되어 있지 않으면 필요 하지 않습니다.또한보십시오:
또 다른 접근법은 ...
> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.
... 그리고 아직 또 하나.
> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
밑줄과 같은 것을 추가하려면 이스케이프 (\)를 사용하십시오.
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
+ = 연산자가 이제 허용 되더라도 2004 년 Bash 3.1 에 도입되었습니다 .
이전 Bash 버전에서이 연산자를 사용하는 스크립트는 운이 좋으면 "명령을 찾을 수 없음"오류 또는 "예기치 않은 토큰 근처의 구문 오류"와 함께 실패합니다.
이전 버전과의 호환성에 관심이있는 사용자는 선택한 답변에 언급 된 것과 같이 이전 표준 Bash 연결 방법을 사용하십시오.
foo="Hello"
foo="$foo World"
echo $foo
> 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
이것이 두 문자열을 연결하는 방법입니다.
var1='hello'
var2='world'
var3=$var1" "$var2
echo $var3
var3=$var1\ $var2
동일한 효과를 갖는다
성능에 대한 우려가 있지만 데이터가 제공되지 않습니다. 간단한 테스트를 제안하겠습니다.
(노트: 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.54432MB 를 얻었음을 나타냅니다 . 보다 세분화 된 그래프와 실패 지점을 얻기 위해 코드 를 데이터 배가에서 상수 추가로 변경할 수 있습니다 . 그러나 이것이 귀하에게 치료 여부를 결정하기에 충분한 정보를 제공해야한다고 생각합니다. 개인적으로 100MB 미만은 아닙니다. 귀하의 마일리지가 다를 수 있습니다.
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
나는 빠른 기능을 만드는 것을 좋아합니다.
#! /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"에서 작동했습니다