Câu hỏi Làm thế nào để nối chuỗi biến trong Bash


Trong PHP, các chuỗi được nối với nhau như sau:

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

Đây, $foo trở thành "Hello World".

Làm thế nào điều này được thực hiện trong Bash?


2102
2017-11-15 05:38


gốc


foo="Hello"  foo=$foo" World"  echo $foo      điều này thay vì làm việc cho "#! / bin / sh" - parasrish
Phải làm gì nếu bạn muốn HelloWorld không có không gian? - Adi


Các câu trả lời:


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

Nói chung để nối hai biến bạn chỉ có thể viết chúng sau cái khác:

a='hello'
b='world'
c=$a$b
echo $c
> helloworld

2852
2017-11-15 05:41



Có lẽ tốt để có thói quen đưa $foo bên trong dấu ngoặc kép, cho những lúc nó thực sự quan trọng. - Cascabel
Chúng tôi được dạy để luôn luôn làm điều đó bởi vì khi thay thế diễn ra, không gian sẽ bị bỏ qua bởi vỏ, nhưng dấu ngoặc kép sẽ luôn luôn bảo vệ những khoảng trống đó. - Strawberry
Có phải có một không gian trong ví dụ đầu tiên của bạn? Có thể làm điều gì đó như foo="$fooworld"? Tôi sẽ không ... - nonsensickle
@nonsensickle Điều đó sẽ tìm kiếm một biến có tên fooworld. Điều chỉnh được thực hiện với niềng răng, như trong foo="${foo}world"... - twalberg
@ JVE999 Vâng, điều đó cũng hoạt động, mặc dù theo ý kiến ​​của tôi nó không hoàn toàn tốt cho mã rõ ràng ... Nhưng đó có thể chỉ là sở thích của tôi ... Có một vài cách khác nó có thể được thực hiện là tốt - điểm là đảm bảo tên biến được tách biệt với các phần không phải tên biến để phân tích cú pháp chính xác. - twalberg


Bash cũng hỗ trợ toán tử + = như trong bảng điểm sau:

$ A="X Y"
$ A+="Z"
$ echo "$A"
X YZ

939
2017-11-15 08:33



Điều này là tốt hơn nhiều so với câu trả lời được chấp nhận, cảm ơn! Đã thêm "chắp thêm" làm thẻ để làm cho câu hỏi này dễ tìm hơn. - noamtm
Tôi có thể sử dụng cú pháp này với từ khóa xuất không? ví dụ. export A+="Z" hoặc có thể A biến chỉ cần được xuất khẩu một lần? - levesque
@levesque: Cả hai :-). Các biến chỉ cần được xuất một lần, nhưng export A+=Z hoạt động khá tốt. - thkala
Vì đây là một bashism, tôi nghĩ rằng nó đáng nói đến là bạn không bao giờ nên sử dụng #!/bin/sh trong một kịch bản sử dụng công trình này. - Score_Under
Nó đặc biệt và chỉ có một toán tử cộng-bằng. Đó là, không giống như Javascript, trong Bash, echo $ A + $ B in "X Y + Z" - phpguru


Bash trước

Vì câu hỏi này dành riêng cho Bash, phần đầu tiên của câu trả lời sẽ trình bày các cách khác nhau để thực hiện điều này một cách chính xác:

+=: Nối vào biến

Cú pháp += có thể được sử dụng theo nhiều cách khác nhau:

Nối thêm vào chuỗi var+=...

(Bởi vì tôi tiết kiệm, tôi sẽ chỉ sử dụng hai biến foo và a và sau đó sử dụng lại như cũ trong toàn bộ câu trả lời. ;-)

a=2
a+=4
echo $a
24

Sử dụng Câu hỏi tràn ngăn xếp cú pháp,

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

hoạt động tốt!

Nối thêm vào một số nguyên ((var+=...))

biến a là một chuỗi, nhưng cũng là một số nguyên

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

Nối vào một mảng var+=(...)

Của chúng tôi a cũng là một mảng chỉ có một phần tử.

echo ${a[@]}
36

a+=(18)

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

Lưu ý rằng giữa các dấu ngoặc đơn, có một không gian tách mảng. Nếu bạn muốn lưu trữ một chuỗi chứa các dấu cách trong mảng của mình, bạn phải gửi kèm theo chúng:

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

Hmm .. đây không phải là lỗi, nhưng một tính năng... Để ngăn chặn phát ban cố gắng phát triển !", bạn có thể:

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: Tái tạo biến bằng cách sử dụng được xây dựng trong chỉ huy

Các printf  được xây dựng trong lệnh cho một cách mạnh mẽ để vẽ định dạng chuỗi. Vì đây là một Bash được xây dựng trong, có một tùy chọn để gửi chuỗi được định dạng đến một biến thay vì in trên stdout:

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

Ở đó có bảy người dây trong mảng này. Vì vậy, chúng tôi có thể tạo chuỗi có định dạng chứa chính xác bảy đối số vị trí:

printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'

Hoặc chúng ta có thể sử dụng một chuỗi định dạng đối số sẽ được lặp lại khi nhiều đối số được gửi ...

Lưu ý rằng a vẫn là một mảng! Chỉ có yếu tố đầu tiên được thay đổi!

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!")'

Dưới bash, khi bạn truy cập vào một tên biến mà không chỉ định chỉ mục, bạn luôn chỉ giải quyết phần tử đầu tiên!

Vì vậy, để lấy mảng trường 7 của chúng ta, chúng ta chỉ cần thiết lập lại phần tử thứ nhất:

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!")'

Một chuỗi định dạng đối số với nhiều đối số được chuyển đến:

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

Sử dụng Câu hỏi tràn ngăn xếp cú pháp:

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

Nota: Việc sử dụng dấu ngoặc kép có thể hữu ích cho việc điều khiển các chuỗi chứa spaces, tabulations và / hoặc newlines

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

Shell bây giờ

Dưới POSIX vỏ, bạn không thể sử dụng bashisms, vì vậy không có được xây dựng trong  printf.

Về cơ bản

Nhưng bạn có thể chỉ cần làm:

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

Được định dạng, sử dụng chia đôi  printf

Nếu bạn muốn sử dụng các công trình phức tạp hơn, bạn phải sử dụng cái nĩa (quy trình con mới tạo công việc và trả lại kết quả qua stdout):

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

Trong lịch sử, bạn có thể sử dụng backticks để lấy kết quả của một cái nĩa:

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

Nhưng điều này không dễ dàng cho làm tổ:

foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013

với backticks, bạn phải thoát khỏi dĩa bên trong với dấu gạch chéo ngược:

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

807
2017-08-04 10:04



Các += nhà điều hành cũng nhanh hơn nhiều $a="$a$b" trong các thử nghiệm của tôi .. Điều đó có ý nghĩa. - Matt
Câu trả lời này là tuyệt vời, nhưng tôi nghĩ rằng nó thiếu var=${var}.sh ví dụ từ các câu trả lời khác, rất hữu ích. - geneorama
Là bash vỏ chỉ có += nhà điều hành? Tôi muốn xem nó có đủ di động không - dashesy
@dashesy no. i'ts chắc chắn không phải là vỏ duy nhất với += nhà điều hành, nhưng tất cả những cách này bashisms, do đó, không di động! Thậm chí bạn có thể gặp lỗi đặc biệt trong trường hợp phiên bản bash sai! - F. Hauri


Bạn cũng có thể làm nó như vậy:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh

114
2017-10-28 03:09



Trong khi không có ký tự đặc biệt, cũng như không gian được sử dụng, dấu ngoặc kép, dấu ngoặc kép và dấu ngoặc nhọn là vô ích: var=myscript;var=$var.sh;echo $var sẽ có tác dụng tương tự (Công việc này dưới bash, dấu gạch ngang, busybox và những người khác). - F. Hauri


bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"

Sẽ đầu ra

helloohaikthxbye

Điều này rất hữu ích khi      $blaohai dẫn đến lỗi không tìm thấy biến. Hoặc nếu bạn có dấu cách hoặc các ký tự đặc biệt khác trong chuỗi của bạn. "${foo}" thoát đúng mọi thứ bạn đưa vào đó.


103
2017-07-25 15:48



Không hoạt động. Tôi nhận được "backupstorefolder: lệnh không tìm thấy" từ bash nơi "backupstorefolder" là tên của một biến. - Zian Choy
Điều này giúp cú pháp làm nổi bật khá một chút, và loại bỏ một số sự mơ hồ của con người. - Ray Foss


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


35
2017-11-15 05:44



Đây là câu trả lời hữu ích nhất cho kịch bản lệnh shell. Tôi đã tìm thấy bản thân mình trong 30 phút cuối cùng bởi vì tôi đã có một không gian trước và sau dấu bằng !! - Stefan
foo = "$ {foo} Thế giới" - XXL


Cách tôi giải quyết vấn đề chỉ là

$a$b

Ví dụ,

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

sản xuất

Hello World

Nếu bạn cố gắng nối một chuỗi với một chuỗi khác, ví dụ:

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

sau đó echo "$c" sẽ sản xuất

Hello World

có thêm không gian.

$aWorld

không hoạt động, như bạn có thể tưởng tượng, nhưng

${a}World

sản xuất

HelloWorld

29
2018-03-07 16:43



...vì thế ${a}\ World sản xuất Hello World - XavierStuvw


$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop

22
2017-11-15 05:42