PHP'de, dizeler aşağıdaki gibi bir araya getirilir:
$foo = "Hello";
$foo .= " World";
Burada $foo
"Merhaba Dünya" olur.
Bash'de bu nasıl başarılır?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
PHP'de, dizeler aşağıdaki gibi bir araya getirilir:
$foo = "Hello";
$foo .= " World";
Burada $foo
"Merhaba Dünya" olur.
Bash'de bu nasıl başarılır?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
Yanıtlar:
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
Genel olarak iki değişkeni birleştirmek için bunları birbiri ardına yazabilirsiniz:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
$foo
önemli olduğu zamanlar için, çift tırnak içine alma alışkanlığı almak için iyi .
foo="$fooworld"
? Ben değil sanırım ...
fooworld
. foo="${foo}world"
Bash ayrıca +=
bu kodda gösterildiği gibi bir operatörü destekler :
$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
export A+="Z"
veya A
değişkenin yalnızca bir kez dışa aktarılması gerekir?
export A+=Z
oldukça iyi çalışır.
#!/bin/sh
bu yapıyı kullanan bir senaryoda asla kullanmamanız gerektiğini belirtmek gerekir .
bash
bazı diğer gelişmiş kabuklarda desteklenen kabuk özelliğidir . busybox sh
Veya dash
( /bin/sh
bir çok dağıtımda) veya /bin/sh
FreeBSD'de sağlanan gibi diğer kabuklar altında çalışmayacaktır .
Bu soru özellikle Bash için geçerli olduğundan, cevabın ilk kısmı bunu doğru bir şekilde yapmanın farklı yollarını sunacaktı:
+=
: Değişkene ekleSözdizimi +=
farklı şekillerde kullanılabilir:
var+=...
Ben tutumlu olduğum için (ben sadece iki değişken kullanacağız foo
ve a
ardından tüm yanıtında aynı tekrar kullanabilirsiniz. ;-)
a=2
a+=4
echo $a
24
Yığın Taşması soru sözdizimini kullanarak ,
foo="Hello"
foo+=" World"
echo $foo
Hello World
iyi çalışıyor!
((var+=...))
değişken a
bir dizedir, aynı zamanda bir tamsayıdır
echo $a
24
((a+=12))
echo $a
36
var+=(...)
Bizim a
de sadece bir elementin dizisidir.
echo ${a[@]}
36
a+=(18)
echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18
Parantezler arasında boşlukla ayrılmış bir dizi olduğunu unutmayın . Dizinizde boşluklar içeren bir dize saklamak istiyorsanız bunları dizelemeniz gerekir:
a+=(one word "hello world!" )
bash: !": event not found
Hmm .. bu bir hata değil, bir özellik ... Bash'in gelişmesini önlemek için !"
şunları yapabilirsiniz:
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
: Yerleşik komutu kullanarak değişkeni yeniden oluşturprintf
Yerleşik komut dizesi biçimi çizim güçlü bir yol sunar. Bu bir Bash yerleşimi olduğundan, üzerine yazdırmak yerine bir değişkene biçimlendirilmiş dize gönderme seçeneği vardır stdout
:
echo ${a[@]}
36 18 one word hello world! hello world! hello world!
Bu dizide yedi dize var . Böylece, tam olarak yedi konum bağımsız değişkeni içeren biçimlendirilmiş bir dize oluşturabiliriz:
printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'
Ya da gönderilen argüman kadar tekrarlanacak bir argüman formatı dizesi kullanabiliriz ...
Bizim a
hala bir dizi olduğunu unutmayın ! Sadece ilk eleman değiştirildi!
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 altında, dizin belirtmeden bir değişken adına eriştiğinizde, her zaman yalnızca ilk öğeye hitap edersiniz!
Bu nedenle, yedi alan dizimizi almak için yalnızca 1. öğeyi yeniden ayarlamamız gerekiyor:
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!")'
Birçok argümanın geçtiği bir argüman biçimi dizesi:
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: kullanımı çift tırnak içerirler dizeleri işleme için yararlı olabilir spaces
, tabulations
ve / veyanewlines
printf -v foo "%s World" "$foo"
POSIX kabuğu altında , bashisms'i kullanamazsınız , bu yüzden yerleşik yoktur printf
.
Ancak şunları yapabilirsiniz:
foo="Hello"
foo="$foo World"
echo $foo
Hello World
printf
Daha karmaşık yapılar kullanmak istiyorsanız, bir çatal kullanmanız gerekir (işi yapan ve sonucu geri getiren yeni alt süreç stdout
):
foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World
Tarihsel olarak, çatalın sonucunu almak için ters tırnakları kullanabilirsiniz :
foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World
Ancak bu yuvalama için kolay değildir :
foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013
backticks ile, iç çatallardan ters eğik çizgilerle kaçmanız gerekir :
foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013
+=
Operatör çok daha hızlı daha da $a="$a$b"
mantıklı hangisi .. benim testlerde.
var=${var}.sh
diğer cevapların örneğini kaçırıyor , ki bu çok faydalı.
bash
sadece kabuk +=
operatörü? Yeterince taşınabilir olup olmadığını görmek istiyorum
+=
operatör ile tek kabuk değil , ama tüm bu yollar bashisms , yani taşınabilir değil! Yanlış bash sürümünde bile özel bir hatayla karşılaşabilirsiniz!
Bunu da yapabilirsiniz:
$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh
var=myscript;var=$var.sh;echo $var
aynı etkileri olacaktır (Bu bash, tire, busybox ve diğerleri altında çalışır).
echo $var2
, üretmezmyscript2
.
Değişken adında yasadışı nokta nedeniyle bu çalışma . Başka echo ${var}2
ya da cevabımı gör
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"
Çıktı olacak
helloohaikthxbye
Bu, $blaohai
değişken bulunamadı hatasına yol açtığında yararlıdır
. Veya dizelerinizde boşluk veya başka özel karakterler varsa. "${foo}"
içine koyduğunuz her şeyden kaçar.
foo="Hello "
foo="$foo World"
Sorunu çözme şeklim sadece
$a$b
Örneğin,
a="Hello"
b=" World"
c=$a$b
echo "$c"
hangi üretir
Hello World
Örneğin, bir dizeyi başka bir dizeyle birleştirmeye çalışırsanız,
a="Hello"
c="$a World"
o echo "$c"
zaman üretecek
Hello World
ekstra alana sahip.
$aWorld
Tahmin edebileceğiniz gibi çalışmıyor, ama
${a}World
üretir
HelloWorld
${a}\ World
üretirHello World
c=$a$b
aynı şeyi yapmak için buraya c=$a World
(koşmak etmeye çalışacağını World
komut olarak). Sanırım bu, değişkenler genişletilmeden önce atamanın ayrıştırıldığı anlamına gelir ..
İşte cevapların çoğunun neden bahsettiğine dair kısa bir özet.
Diyelim ki iki değişkenimiz var ve 1 $ 'one' olarak ayarlandı:
set one two
a=hello
b=world
Aşağıdaki tabloda, değerleri birleştirebileceğimiz a
ve b
yeni bir değişken oluşturabileceğimiz farklı bağlamlar açıklanmaktadır 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
Birkaç not:
+=
büyük bir dize küçük artışlarla, özellikle de bir döngüde oluşturuluyorsa, performans açısından daha iyidir{}
genişlemelerini netleştirmek için değişken adları etrafında kullanın (yukarıdaki tabloda 2. satırda olduğu gibi). Satır 3 ve 4'te görüldüğü gibi, {}
bir değişken kabuk değişken adında geçerli bir ilk karakter olan, yani alfabe veya alt çizgi olan bir dize ile birleştirilmedikçe buna gerek yoktur .Ayrıca bakınız:
Yine başka bir yaklaşım ...
> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.
... ve yine bir tane daha.
> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
Alt çizgi gibi bir şey eklemek istiyorsanız escape (\) kullanın
FILEPATH=/opt/myfile
Bu mu değil çalışır:
echo $FILEPATH_$DATEX
Bu iyi çalışıyor:
echo $FILEPATH\\_$DATEX
echo $a\_$b
yapardı. Nik O'Lai'nin yorumunda ima edildiği gibi alt çizgi düzenli bir karakterdir. Beyaz boşlukların kullanımı, dizeler, yankı ve birleştirme için çok daha hassastır - \
bu konu zaman zaman geri döndükçe bu konuyu iyice kullanabilir ve okuyabilir.
Tırnak işaretleriyle en basit yol:
B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
var=$B$b"a"; echo Hello\ $var
inanıyorum
Tırnak işaretleri olmadan birleştirebilirsiniz. İşte bir örnek:
$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3
Bu son ifade "OpenSystems" yazacaktır (tırnak işaretleri olmadan).
Bu bir Bash betiği örneğidir:
v1=hello
v2=world
v3="$v1 $v2"
echo $v3 # Output: hello world
echo "$v3" # Output: hello world
+ = Operatörüne şimdi izin verilse bile, 2004'te Bash 3.1'de tanıtıldı .
Eski Bash sürümlerinde bu işleci kullanan herhangi bir komut dosyası, şanslıysanız bir "komut bulunamadı" hatasıyla veya "beklenmeyen belirtecin yanında bir sözdizimi hatasıyla" başarısız olur.
Geriye dönük uyumluluğu önemseyenler için, seçilen cevapta belirtilenler gibi eski standart Bash birleştirme yöntemlerine sadık kalın:
foo="Hello"
foo="$foo World"
echo $foo
> Hello World
${}
Dize değişkeni genişletmek için kıvırcık parantez kullanmayı tercih ederim :
foo="Hello"
foo="${foo} World"
echo $foo
> Hello World
Kıvırcık parantezler Sürekli dize kullanımına uyacaktır:
foo="Hello"
foo="${foo}World"
echo $foo
> HelloWorld
Aksi takdirde kullanmak foo = "$fooWorld"
işe yaramaz.
Ne yapmaya çalışıyorsun ise bölünmüş birkaç satır içine bir dize, bir ters eğik çizgi kullanabilirsiniz:
$ a="hello\
> world"
$ echo $a
helloworld
Aralarında bir boşluk bırakarak:
$ a="hello \
> world"
$ echo $a
hello world
Bu ayrıca aralarına yalnızca bir boşluk ekler:
$ a="hello \
> world"
$ echo $a
hello world
Daha güvenli yolu:
a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD
Boşluk içeren dizeler komutun bir parçası olabilir, bu hataları önlemek için "$ XXX" ve "$ {XXX}" kullanın.
Artı + = ile ilgili diğer cevaba bir göz atın
d=DD DD
verecekti DD: command not found
. Tüm işlenenler doğru biçimlendirilmişse ve zaten gerekli boşlukları içeriyorsa, s=${a}${b}${c}${d}; echo $s
daha az alıntı işaretiyle birleştirebilirsiniz . Ayrıca, \
bu sorunları önlemek için (kaçan boşluk) kullanabilirsiniz - d=echo\ echo
oysa herhangi bir yankı çağrısı başlatmaz d=echo echo
.
a="Hello,"
a=$a" World!"
echo $a
İki dizeyi bu şekilde birleştirirsiniz.
" World"
Orijinal dizeye ekleme örneğinizse, şunlar olabilir:
#!/bin/bash
foo="Hello"
foo=$foo" World"
echo $foo
Çıktı:
Hello World
var1='hello'
var2='world'
var3=$var1" "$var2
echo $var3
var3=$var1\ $var2
aynı etkiye sahiptir
Performansla ilgili dile getirilen endişeler var, ancak veri sunulmuyor. Basit bir test önereyim.
(NOT: date
macOS'ta nanosaniye sunmaz, bu yüzden Linux'ta yapılmalıdır.)
İçeriğiyle GitHub'da append_test.sh oluşturdum :
#!/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
Test 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
Test 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
Hatalar, Bash'ımın çökmeden önce 335.54432 MB'a kadar çıktığını gösteriyor . Daha ayrıntılı bir grafik ve hata noktası elde etmek için kodu verileri ikiye katlamaktan bir sabit eklemeye değiştirebilirsiniz . Ama bence bu size önem verip vermeyeceğinize karar vermeniz için yeterli bilgi vermelidir. Şahsen, 100 MB altı yapmam. Kilometreniz değişebilir.
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"
Bunun işe yaramayacağını unutmayın
foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar
$ foo düşürdüğü ve size bıraktığı gibi:
PREFIX_WORLD
ancak bu işe yarayacaktır:
foobar=PREFIX_"$foo"_"$bar"
ve size doğru çıktıyı bırakın:
PREFIX_HELLO_WORLD
İşte AWK ile olan :
$ foo="Hello"
$ foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
$ echo $foo
Hello World
Uygun olduğunda bunu yaparım: Satır içi komut kullanın!
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
Bence, iki dizeyi birleştirmenin en basit yolu, bunu sizin için yapan bir işlev yazmak ve sonra bu işlevi kullanmaktır.
function concat ()
{
prefix=$1
suffix=$2
echo "${prefix}${suffix}"
}
foo="Super"
bar="man"
concat $foo $bar # Superman
alien=$(concat $foo $bar)
echo $alien # Superman
Hızlı bir iş yapmaktan hoşlanıyorum.
#! /bin/sh -f
function combo() {
echo $@
}
echo $(combo 'foo''bar')
Bir kedinin derisini almanın başka bir yolu. Bu kez fonksiyonlarla: D
Henüz PHP hakkında bir bilgim yok ama bu Linux Bash ile çalışıyor. Bir değişkeni etkilemek istemiyorsanız, bunu deneyebilirsiniz:
read pp; *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;
>Hello World!
'Merhaba' veya '!' Yerine başka bir değişken yerleştirebilirsiniz. Daha fazla dizeyi de birleştirebilirsiniz.
foo="Hello"
foo=$foo" World"
echo $foo
bu oldukça "#! / bin / sh" için çalıştı