Dalam PHP, string digabungkan bersama sebagai berikut:
$foo = "Hello";
$foo .= " World";
Sini, $foo
menjadi "Hello World".
Bagaimana ini bisa dilakukan di Bash?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
Dalam PHP, string digabungkan bersama sebagai berikut:
$foo = "Hello";
$foo .= " World";
Sini, $foo
menjadi "Hello World".
Bagaimana ini bisa dilakukan di Bash?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
Jawaban:
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
Secara umum untuk menggabungkan dua variabel, Anda cukup menuliskannya satu per satu:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
$foo
tanda kutip ganda, untuk saat-saat ketika itu benar-benar penting.
foo="$fooworld"
? Saya akan berasumsi tidak ...
fooworld
. Mengacaukan yang dilakukan dengan kawat gigi, seperti pada foo="${foo}world"
...
Bash juga mendukung +=
operator seperti yang ditunjukkan dalam kode ini:
$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
export A+="Z"
atau mungkin A
variabel hanya perlu diekspor sekali?
export A+=Z
berfungsi dengan cukup baik.
#!/bin/sh
skrip menggunakan konstruksi ini.
bash
dan beberapa shell yang lebih canggih lainnya. Ini tidak akan berfungsi di bawah busybox sh
atau dash
(yang ada /bin/sh
di banyak distro), atau shell lain seperti yang /bin/sh
disediakan di FreeBSD.
Karena pertanyaan ini khusus untuk Bash , bagian pertama dari jawaban saya akan menyajikan berbagai cara untuk melakukan ini dengan benar:
+=
: Tambahkan ke variabelSintaks +=
dapat digunakan dengan berbagai cara:
var+=...
(Karena saya hemat, saya hanya akan menggunakan dua variabel foo
dan a
kemudian kembali menggunakan yang sama di seluruh jawaban. ;-)
a=2
a+=4
echo $a
24
Menggunakan sintaks pertanyaan Stack Overflow ,
foo="Hello"
foo+=" World"
echo $foo
Hello World
bekerja dengan baik!
((var+=...))
variabel a
adalah string, tetapi juga bilangan bulat
echo $a
24
((a+=12))
echo $a
36
var+=(...)
Kami a
juga merupakan array dari hanya satu elemen.
echo ${a[@]}
36
a+=(18)
echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18
Perhatikan bahwa di antara tanda kurung, ada array yang dipisahkan spasi . Jika Anda ingin menyimpan string yang berisi spasi di array Anda, Anda harus melampirkannya:
a+=(one word "hello world!" )
bash: !": event not found
Hmm .. ini bukan bug, tetapi fitur ... Untuk mencegah bash mencoba dikembangkan !"
, Anda dapat:
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
: Membangun ulang variabel menggunakan builtin perintahThe printf
builtin perintah memberikan cara yang ampuh untuk menggambar format string. Karena ini adalah Bash bawaan , ada opsi untuk mengirim string yang diformat ke variabel alih-alih mencetak stdout
:
echo ${a[@]}
36 18 one word hello world! hello world! hello world!
Ada tujuh string dalam array ini. Jadi kita bisa membangun string yang diformat yang mengandung tujuh argumen posisi:
printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'
Atau kita bisa menggunakan satu string format argumen yang akan diulang karena banyak argumen yang diajukan ...
Perhatikan bahwa kami a
masih berupa array! Hanya elemen pertama yang diubah!
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!")'
Di bawah bash, ketika Anda mengakses nama variabel tanpa menentukan indeks, Anda selalu membahas elemen pertama saja!
Jadi untuk mengambil tujuh array bidang, kita hanya perlu mengatur ulang elemen 1:
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!")'
Satu string format argumen dengan banyak argumen diteruskan ke:
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
Catatan: Penggunaan tanda kutip ganda mungkin berguna untuk memanipulasi string yang berisi spaces
, tabulations
dan / ataunewlines
printf -v foo "%s World" "$foo"
Di bawah shell POSIX , Anda tidak dapat menggunakan bashism , jadi tidak ada builtin printf
.
Tapi Anda bisa melakukannya:
foo="Hello"
foo="$foo World"
echo $foo
Hello World
printf
Jika Anda ingin menggunakan konstruksi yang lebih canggih, Anda harus menggunakan garpu (proses anak baru yang menghasilkan pekerjaan dan mengembalikan hasilnya melalui stdout
):
foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World
Secara historis, Anda bisa menggunakan backtick untuk mengambil hasil dari fork :
foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World
Tapi ini tidak mudah untuk bersarang :
foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013
dengan backticks, Anda harus melarikan diri dari garpu dalam dengan garis miring terbalik :
foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013
+=
Operator juga jauh lebih cepat daripada $a="$a$b"
di tes saya .. Yang masuk akal.
var=${var}.sh
contoh dari jawaban lain, yang sangat berguna.
bash
satu-satunya shell dengan +=
operator? Saya ingin melihat apakah ini cukup portabel
+=
operator, tetapi semua cara ini adalah bashism , jadi tidak portabel! Bahkan Anda dapat menemukan bug khusus jika versi bash salah!
Anda juga dapat melakukan ini:
$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh
var=myscript;var=$var.sh;echo $var
akan memiliki efek yang sama (Ini bekerja di bawah bash, tanda hubung, kotak sibuk dan lain-lain).
echo $var2
tidak menghasilkanmyscript2
.
ilegal pada nama variabel. Jika lain echo ${var}2
atau lihat jawaban saya
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"
Akan menghasilkan
helloohaikthxbye
Ini berguna ketika
$blaohai
mengarah ke variabel tidak ditemukan kesalahan. Atau jika Anda memiliki spasi atau karakter khusus lainnya di string Anda. "${foo}"
benar lolos apa pun yang Anda masukkan ke dalamnya.
foo="Hello "
foo="$foo World"
Cara saya memecahkan masalah itu adil
$a$b
Sebagai contoh,
a="Hello"
b=" World"
c=$a$b
echo "$c"
yang menghasilkan
Hello World
Jika Anda mencoba menggabungkan string dengan string lain, misalnya,
a="Hello"
c="$a World"
maka echo "$c"
akan menghasilkan
Hello World
dengan ruang ekstra.
$aWorld
tidak bekerja, seperti yang Anda bayangkan, tetapi
${a}World
menghasilkan
HelloWorld
${a}\ World
menghasilkanHello World
c=$a$b
sini untuk melakukan hal yang sama c=$a World
(yang akan mencoba dijalankan World
sebagai perintah). Saya kira itu berarti tugas diuraikan sebelum variabel diperluas ..
Berikut ini ringkasan singkat dari apa yang dibicarakan oleh sebagian besar jawaban.
Katakanlah kita memiliki dua variabel dan $ 1 diatur ke 'satu':
set one two
a=hello
b=world
Tabel di bawah ini menjelaskan berbagai konteks di mana kita dapat menggabungkan nilai a
dan b
untuk membuat variabel baru 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
Beberapa catatan:
+=
lebih baik dari sudut pandang kinerja jika string besar sedang dibangun dalam peningkatan kecil, terutama dalam satu lingkaran{}
sekitar nama variabel untuk mendisambiguasikan ekspansi mereka (seperti pada baris 2 pada tabel di atas). Seperti terlihat pada baris 3 dan 4, tidak perlu {}
kecuali variabel sedang digabungkan dengan string yang dimulai dengan karakter yang merupakan karakter pertama yang valid dalam nama variabel shell, yaitu alfabet atau garis bawah.Lihat juga:
Namun pendekatan lain ...
> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.
... dan satu lagi.
> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
Jika Anda ingin menambahkan sesuatu seperti garis bawah, gunakan escape (\)
FILEPATH=/opt/myfile
Ini tidak berfungsi:
echo $FILEPATH_$DATEX
Ini berfungsi dengan baik:
echo $FILEPATH\\_$DATEX
echo $a\_$b
akan dilakukan. Seperti yang diisyaratkan dalam komentar Nik O'Lai, garis bawah adalah karakter biasa. Penanganan ruang putih jauh lebih sensitif untuk string, gema dan rangkaian --- seseorang dapat menggunakan \
dan membaca utas ini secara menyeluruh karena masalah ini muncul kembali sekarang dan kemudian.
Cara paling sederhana dengan tanda kutip:
B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
var=$B$b"a"; echo Hello\ $var
akan melakukan, saya percaya
Anda dapat menggabungkan tanpa tanda kutip. Berikut ini sebuah contoh:
$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3
Pernyataan terakhir ini akan mencetak "OpenSystems" (tanpa tanda kutip).
Ini adalah contoh skrip Bash:
v1=hello
v2=world
v3="$v1 $v2"
echo $v3 # Output: hello world
echo "$v3" # Output: hello world
Bahkan jika operator + = sekarang diizinkan, ia telah diperkenalkan di Bash 3.1 pada tahun 2004.
Setiap skrip yang menggunakan operator ini pada versi Bash yang lebih lama akan gagal dengan kesalahan "perintah tidak ditemukan" jika Anda beruntung, atau "kesalahan sintaksis dekat token yang tidak terduga".
Bagi mereka yang peduli tentang kompatibilitas ke belakang, tetap menggunakan metode penggabungan Bash standar yang lebih lama, seperti yang disebutkan dalam jawaban yang dipilih:
foo="Hello"
foo="$foo World"
echo $foo
> Hello World
Saya lebih suka menggunakan kurung keriting ${}
untuk memperluas variabel dalam string:
foo="Hello"
foo="${foo} World"
echo $foo
> Hello World
Kurung keriting akan cocok dengan penggunaan string Berkelanjutan:
foo="Hello"
foo="${foo}World"
echo $foo
> HelloWorld
Kalau tidak menggunakan foo = "$fooWorld"
tidak akan berfungsi.
Jika yang ingin Anda lakukan adalah membagi string menjadi beberapa baris, Anda dapat menggunakan garis miring terbalik:
$ a="hello\
> world"
$ echo $a
helloworld
Dengan satu ruang di antaranya:
$ a="hello \
> world"
$ echo $a
hello world
Yang ini juga menambahkan hanya satu ruang di antara:
$ a="hello \
> world"
$ echo $a
hello world
Cara yang lebih aman:
a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD
String yang berisi spasi dapat menjadi bagian dari perintah, gunakan "$ XXX" dan "$ {XXX}" untuk menghindari kesalahan ini.
Plus lihat jawaban lain tentang + =
d=DD DD
akan memberikan DD: command not found
--- perhatikan itu adalah DD terakhir, bukan d yang tidak ditemukan. Jika semua operan diformat dengan benar dan sudah berisi ruang yang diperlukan, Anda dapat menyatukan dengan s=${a}${b}${c}${d}; echo $s
, dengan sedikit tanda kutip. Anda juga dapat menggunakan \
(escaped whitespace) untuk menghindari masalah ini --- d=echo\ echo
tidak akan meluncurkan permintaan gema, sedangkan d=echo echo
akan.
Ada satu kasus khusus di mana Anda harus berhati-hati:
user=daniel
cat > output.file << EOF
"$user"san
EOF
Akan menampilkan "daniel"san
, dan tidak danielsan
, seperti yang Anda inginkan. Dalam hal ini yang harus Anda lakukan sebagai gantinya:
user=daniel
cat > output.file << EOF
${user}san
EOF
a="Hello,"
a=$a" World!"
echo $a
Ini adalah bagaimana Anda menggabungkan dua string.
Jika itu sebagai contoh Anda menambahkan " World"
ke string asli, maka itu bisa:
#!/bin/bash
foo="Hello"
foo=$foo" World"
echo $foo
Hasil:
Hello World
var1='hello'
var2='world'
var3=$var1" "$var2
echo $var3
var3=$var1\ $var2
memiliki efek yang sama
Ada kekhawatiran yang disuarakan tentang kinerja, tetapi tidak ada data yang ditawarkan. Izinkan saya menyarankan tes sederhana.
(CATATAN: date
pada macOS tidak menawarkan nanodetik, jadi ini harus dilakukan di Linux.)
Saya telah membuat append_test.sh di GitHub dengan konten:
#!/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
Tes 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
Tes 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
Kesalahan menunjukkan bahwa Bash saya hingga 335.54432 MB sebelum crash. Anda bisa mengubah kode dari menggandakan data menjadi menambahkan konstanta untuk mendapatkan grafik yang lebih terperinci dan titik kegagalan. Tapi saya pikir ini harus memberi Anda informasi yang cukup untuk memutuskan apakah Anda peduli. Secara pribadi, di bawah 100 MB saya tidak. Jarak tempuh Anda mungkin beragam.
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"
(Coba ini pada host yang tidak produktif !!;)
Saya ingin membuat string dari daftar. Tidak dapat menemukan jawaban untuk itu sehingga saya mempostingnya di sini. Inilah yang saya lakukan:
list=(1 2 3 4 5)
string=''
for elm in "${list[@]}"; do
string="${string} ${elm}"
done
echo ${string}
dan kemudian saya mendapatkan output berikut:
1 2 3 4 5
Perhatikan bahwa ini tidak akan berhasil
foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar
karena tampaknya menjatuhkan $ foo dan meninggalkan Anda dengan:
PREFIX_WORLD
tetapi ini akan berhasil:
foobar=PREFIX_"$foo"_"$bar"
dan meninggalkan Anda dengan output yang benar:
PREFIX_HELLO_WORLD
Saya melakukannya dengan cara ini ketika nyaman: Gunakan perintah inline!
echo "The current time is `date`"
echo "Current User: `echo $USER`"
date "+The current time is %a %b %d %Y +%T"
:, bukan echo ...$(date)
. Under bash baru-baru ini, Anda bisa menulis: printf "The current time is %(%a %b %d %Y +%T)T\n" -1
.
Menurut pendapat saya, cara paling sederhana untuk menggabungkan dua string adalah dengan menulis fungsi yang melakukannya untuk Anda, lalu gunakan fungsi itu.
function concat ()
{
prefix=$1
suffix=$2
echo "${prefix}${suffix}"
}
foo="Super"
bar="man"
concat $foo $bar # Superman
alien=$(concat $foo $bar)
echo $alien # Superman
Saya agak suka membuat fungsi cepat.
#! /bin/sh -f
function combo() {
echo $@
}
echo $(combo 'foo''bar')
Namun cara lain untuk menguliti kucing. Kali ini dengan fungsi: D
Saya belum tahu tentang PHP, tetapi ini bekerja di Linux Bash. Jika Anda tidak ingin memengaruhi variabel, Anda dapat mencoba ini:
read pp; *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;
>Hello World!
Anda dapat menempatkan variabel lain alih-alih 'Halo' atau '!'. Anda dapat menggabungkan lebih banyak string juga.
foo="Hello"
foo=$foo" World"
echo $foo
ini agak berhasil untuk "#! / bin / sh"