it-swarm-tr.com

Bash'de string değişkenleri nasıl birleştiririm?

PHP'de dizeler aşağıdaki şekilde birleştirilir:

$foo = "Hello";
$foo .= " World";

Burada, $foo "Merhaba Dünya" olur.

Bash'de bu nasıl başarılır?

2423
Strawberry
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
> helloworld
3285
codaddict

Bash ayrıca bu kodda gösterildiği gibi bir += operatörünü de destekler:

$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
1026
thkala

Önce bash

Bu soru özellikle Bash için geçerli olduğundan, cevabın ilk kısmı bunu doğru şekilde yapmanın farklı yollarını sunar:

+=: Değişkene ekle

Sözdizimi+=farklı şekillerde kullanılabilir:

Dizeye ekle var+=...

(Ben tutumlu olduğum için, sadece iki değişkeni kullanacağım: foove ave sonra tüm cevaplarda aynısını tekrar kullanacağım. ;-)

a=2
a+=4
echo $a
24

Yığın Taşması sorusu sözdizimini kullanarak,

foo="Hello"
foo+=" World"
echo $foo
Hello World

iyi çalışıyor!

Bir tamsayıya ekleyin ((var+=...))

adeğişkeni bir dizedir, ancak aynı zamanda bir tam sayıdır

echo $a
24
((a+=12))
echo $a
36

Bir diziye ekle var+=(...)

aname__, aynı zamanda sadece bir elementin dizisidir.

echo ${a[@]}
36

a+=(18)

echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18

Parantezler arasında, bir boşlukla ayrılmış dizi olduğuna dikkat edin. Dizinizde boşluk içeren bir dize saklamak istiyorsanız, bunları içine almanız gerekir:

a+=(one Word "hello world!" )
bash: !": event not found

Hmm .. bu bir hata değil, bir özellik ... Bash'ın !" geliştirmeye çalışmasını ö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!")'

printfname__: builtin komutunu kullanarak değişkeni yeniden oluşturun

printfbuiltin komutu dize formatı için güçlü bir yol sunar. Bu bir Bash builtin olduğundan, stdoutüzerine yazdırmak yerine formatlanmış dizgiyi bir değişkene göndermek için bir seçenek vardır:

echo ${a[@]}
36 18 one Word hello world! hello world! hello world!

Bu dizide yedi dizge var. Böylece, tam olarak yedi konumsal argüman 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!'

Veya bir argüman format dizgisi kullanabiliriz, ki bu birçok argüman gönderilmiş olarak tekrarlanacaktır ...

Bizim abizim hala bir dizi olduğunu unutmayın! Sadece ilk eleman değişti!

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 ismine eriştiğinizde, her zaman sadece ilk elemanı ele alırsınız!

Bu yüzden yedi alan dizimizi geri almak için sadece 1. elementi yeniden ayarlamamız gerekir:

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 argüman format dizgisi birçok argümanla iletildi:

printf -v a[0] '<%s>\n' "${a[@]}"
echo "$a"
<36>
<18>
<one>
<Word>
<hello world!>
<hello world!>
<hello world!>

Yığın Taşması sorusu sözdizimini kullanarak:

foo="Hello"
printf -v foo "%s World" $foo
echo $foo
Hello World

Not: çift tırnaklı kullanımı, spacesname__, tabulationsve/veya newlinesiçeren dizeleri işlemek için yararlı olabilir

printf -v foo "%s World" "$foo"

Şimdi kabuk

POSIX Kabuk altında, bashisms kullanamazsınız, bu nedenle yerleşikprintfyoktur.

Temel olarak

Ama basitçe yapabilirsin:

foo="Hello"
foo="$foo World"
echo $foo
Hello World

Forkedprintfkullanılarak biçimlendirildi

Daha karmaşık yapılar kullanmak istiyorsanız, fork kullanmanız gerekir (işi yapan ve sonucu stdoutile döndüren yeni bir alt işlem):

foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World

Tarihsel olarak, bir çatal sonucunu almak için backticks kullanabilirsiniz:

foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World

Ancak bu, nesting 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

geri tepme çubukları ile, iç çatallardan ters eğik çizgi ile çıkmalısınız:

foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013
885
F. Hauri

Bunu da yapabilirsiniz:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh
123
userend
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"

Çıktı olacak

helloohaikthxbye

Bu, $blaohai, bulunmayan bir hataya yol açtığında faydalıdır. Veya dizelerinizde boşluk veya başka özel karakterler varsa. "${foo}", içine koyduğunuz her şeyi düzgün bir şekilde çıkarır.

115
orkoden
foo="Hello "
foo="$foo World"

41
vinothkr

Sorunu çözeceğim yol sadece

$a$b

Örneğin,

a="Hello"
b=" World"
c=$a$b
echo "$c"

hangi üretir

Hello World

Bir dizeyi başka bir dizeyle birleştirmeye çalışırsanız, örneğin

a="Hello"
c="$a World"

o zaman echo "$c" üretecek

Hello World

fazladan bir boşlukla.

$aWorld

çalışma, tahmin edebileceğiniz gibi

${a}World

üretir

HelloWorld
32
Chris Smith
$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop
27
bcosca

İşte çoğu cevapların neden bahsettiğinin kısa bir özeti.

İki değişkenimiz olduğunu varsayalım:

a=hello
b=world

Aşağıdaki tabloda a ve b değerlerini birleştirebileceğimiz farklı bağlamlar, c olan yeni bir değişken yaratılmaktadır.

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

Birkaç not:

  • bir atamanın RHS'sini çift tırnak içine almak, genellikle iyi bir uygulamadır, ancak çoğu durumda oldukça isteğe bağlıdır.
  • 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ının çevresinde {} kullanın (yukarıdaki tabloda 2. satırda olduğu gibi)

Ayrıca bakınız:

20
codeforester

Alt çizgi gibi bir şey eklemek istiyorsanız, escape (\) kullanın.

FILEPATH=/opt/myfile

Bu not work:

echo $FILEPATH_$DATEX

Bu iyi çalışıyor:

echo $FILEPATH\\_$DATEX
20
user2800471

Yine başka bir yaklaşım ...

> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.

... ve bir tane daha.

> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
19
Akseli Palén

Tırnak işareti içeren en basit yol:

B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
15
betontalpfa

Tırnaklar olmadan birleştirebilirsiniz. İşte bir örnek:

$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3

Bu son ifade "OpenSystems" (tırnak işaretleri olmadan) basacaktır.

Bu bir Bash betiğinin bir örneği:

v1=hello
v2=world
v3="$v1       $v2"
echo $v3            # Output: hello world
echo "$v3"          # Output: hello       world
15
mariana soffer

+ = Operatörüne şimdi izin verilse bile, 2004 yılında Bash 3.1 içine girmiştir.

Bu işleci eski Bash sürümlerinde kullanan herhangi bir komut dosyası, şanslıysanız "komut bulunamadı" hatası veya "beklenmeyen belirteci yakınında" sözdizimi hatası "ile başarısız olur.

Geriye dönük uyumluluk umurunda olanlar için, seçilen cevapta belirtilenler gibi eski standart Bash birleştirme yöntemlerine uyun:

foo="Hello"
foo="$foo World"
echo $foo
> Hello World
14
Louis-Félix

Dizedeki değişkeni genişletmek için küme parantezleri ${} kullanmayı tercih ediyorum:

foo="Hello"
foo="${foo} World"
echo $foo
> Hello World

Kıvrımlı parantez Sürekli dizi kullanımına uyacaktır:

foo="Hello"
foo="${foo}World"
echo $foo
> HelloWorld

Aksi takdirde, foo = "$fooWorld" kullanmak işe yaramaz.

13
Nick Tsai

Daha güvenli yol:

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}" tuşlarını kullanın.

Artı + = hakkındaki diğer cevaba bir göz atın

7
Bohdan

Yapmaya çalıştığınız şey, split a dizesini birkaç satır halinde yapmaksa ters eğik çizgi kullanabilirsiniz:

$ a="hello\
> world"
$ echo $a
helloworld

Arada bir boşlukla:

$ a="hello \
> world"
$ echo $a
hello world

Bu, ayrıca şunlara yalnızca bir boşluk ekler:

$ a="hello \
>      world"
$ echo $a
hello world
7
jcarballo

Dikkat etmeniz gereken belirli bir durum var:

user=daniel
cat > output.file << EOF
"$user"san
EOF

Çıktığınız "daniel"san ve istediğiniz gibi danielsandeğil. Bu durumda yerine yapmalısınız:

user=daniel
cat > output.file << EOF
${user}san
EOF
6
diogovk

Orijinal dizeye " World" eklemek için örnek olarak, o zaman olabilir:

#!/bin/bash

foo="Hello"
foo=$foo" World"
echo $foo

Çıktı:

Hello World
5
var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3
5
hari

Performansla ilgili dile getirilen endişeler var ancak veri sunulmuyor. Basit bir test önereyim.

(NOT: macOS'ta date nanosaniye sunmuyor, bu yüzden Linux'ta yapılmalı.)

İçeriği ile 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'in düşmeden önce 335.54432 MB değerine ulaştığını gösteriyor. Daha ayrıntılı bir grafik ve hata noktası elde etmek için kod 'ı iki katına çıkarmak, sabit değer eklemek için verileri ikiye katlamaktan değiştirebilirsiniz. Fakat bunun umrunda olup olmadığına karar vermek için size yeterli bilgi vermesi gerektiğini düşünüyorum. Şahsen, 100 MB'ın altında değilim. Kilometreniz değişebilir.

4
Bruno Bronosky
a="Hello,"
a=$a" World!"
echo $a

İki dizeyi bu şekilde birleştiriyorsunuz.

4
CodeNinjaPI

Bir listeden bir dize oluşturmak istedim. Bunun için bir cevap bulamadım bu yüzden buraya yazıyorum. İşte yaptığım şey:

list=(1 2 3 4 5)
string=''

for Elm in "${list[@]}"; do
    string="${string} ${Elm}"
done

echo ${string}

ve sonra aşağıdaki çıktıyı alıyorum:

1 2 3 4 5
4
Simon Bachmann

Bunun işe yaramayacağını unutmayın.

foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar

görünüşe göre $ foo düşüyor ve sizi bırakıyor:

PREFIX_WORLD

ama bu işe yarayacak:

foobar=PREFIX_"$foo"_"$bar"

ve sizi doğru çıktıya bırakın:

PREFIX_HELLO_WORLD

3
Dss

Uygun olduğunda bu şekilde yapıyorum: Bir satır içi komut kullanın!

echo "The current time is `date`"
echo "Current User: `echo $USER`"
1
Marty

Benim düşünceme göre, iki dizgiyi birleştirmenin en basit yolu, bunu sizin için yapan bir işlev yazmak, sonra da 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
1

İşte bir - AWK :

$ foo="Hello"
$ foo=$(awk -v var=$foo 'BEGIN{print var" World"}')
$ echo $foo
Hello World
1
Avinash Raj