Cách nối các biến chuỗi trong Bash


2767

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

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

Ở đây, $footrở thành "Xin chào thế giới".

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


6
foo="Hello" foo=$foo" World" echo $foo cái này khá hiệu quả với "#! / bin / sh"
ký sinh

1
Phải làm gì nếu bạn muốn HelloWorld không có không gian?
Adi

@Adifoo1="World" foo2="Hello" foo3="$foo1$foo2"
GeneCode

không gian có vấn đề trong bash)
Capibar

Câu trả lời:


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

Nói chung để nối hai biến, bạn chỉ có thể viết từng biến một:

a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World

314
Có lẽ tốt để có được thói quen đặt $foobên trong dấu ngoặc kép, cho những lúc nó thực sự quan trọng.
Cascabel

104
Chúng tôi được dạy phải luôn luôn làm điều đó bởi vì khi sự thay thế diễn ra, các khoảng trắng sẽ bị bỏ qua bởi vỏ, nhưng dấu ngoặc kép sẽ luôn bảo vệ các khoảng trắng đó.
Dâu

62
Có phải có một không gian trong ví dụ đầu tiên của bạn? Có thể làm một cái gì đó như thế foo="$fooworld"nào? Tôi sẽ giả sử không ...
vô nghĩa

341
@nonsensickle Điều đó sẽ tìm kiếm một biến có tên fooworld. Định hướng được thực hiện với niềng răng, như trong foo="${foo}world"...
twalberg

4
@ JVE999 Vâng, điều đó cũng hoạt động, mặc dù theo tôi thì nó không hoàn toàn tốt cho sự rõ ràng của mã ... Nhưng đó có thể chỉ là sở thích của tôi ... Có một số cách khác cũng có thể được thực hiện - vấn đề là đảm bảo tên biến được tách ra khỏi các phần tên không biến để nó phân tích chính xác.
twalberg

1128

Bash cũng hỗ trợ một +=toán tử như trong mã này:

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

2
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ể Abiến chỉ cần được xuất một lần?
levesque

3
@levesque: Cả hai :-). Các biến chỉ cần được xuất một lần, nhưng cũng export A+=Zhoạt động khá độc đáo.
thkala

38
Vì đây là một sự bashism, tôi nghĩ rằng đáng để đề cập rằng bạn không bao giờ nên sử dụng #!/bin/shtrong một kịch bản sử dụng cấu trúc này.
Điểm_Under

2
Đó là cụ thể và chỉ là một toán tử cộng bằng. Đó là, không giống như Javascript, ở Bash, lặp lại $ A + $ B in "X Y + Z"
phpguru

6
Bashism là một tính năng shell chỉ được hỗ trợ bashvà một số shell tiên tiến khác. Nó sẽ không hoạt động dưới busybox shhoặc dash( /bin/shtrên nhiều bản phân phối), hoặc một số shell khác như/bin/sh được cung cấp trên FreeBSD.
Điểm_Under

960

Bash đầu tiên

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

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

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

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

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

a=2
a+=4
echo $a
24

Sử dụng cú pháp câu hỏi Stack Overflow ,

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

hoạt động tốt

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

Biến đổi 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+=(...)

Chúng tôi acũng là một mảng chỉ có một yếu 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 mảng được phân tách bằng dấu cách . Nếu bạn muốn lưu trữ một chuỗi chứa khoảng trắng trong mảng của mình, bạn phải kèm theo chúng:

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

Hmm .. đây không phải là một lỗi, mà là một tính năng ... Để ngăn bash 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: Xây dựng lại biến bằng cách sử dụng nội dung lệnh

Lệnh printf dựng sẵn cung cấp một cách mạnh mẽ để vẽ định dạng chuỗi. Vì đây là một nội dung Bash , có một tùy chọn để gửi chuỗi được định dạng tới 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 chuỗi trong mảng này. Vì vậy, chúng ta có thể xây dựng một 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 có nhiều đối số được gửi ...

Lưu ý rằng chúng tôi avẫ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!")'

Trong bash, khi bạn truy cập một tên biến mà không chỉ định chỉ mục, bạn luôn chỉ xử lý phần tử đầu tiên!

Vì vậy, để lấy lại mảng bảy trường của chúng ta, chúng ta chỉ cần đặt lại phần tử thứ 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!")'

Một chuỗi định dạng đối số có nhiều đối số được truyền cho:

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

Sử dụng cú pháp câu hỏi Stack Overflow :

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

Nota: Việc sử dụng hai dấu ngoặc kép có thể hữu ích cho các thao tác chuỗi có chứa spaces, tabulationsvà / hoặcnewlines

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

Shell bây giờ

Trong vỏ POSIX , bạn không thể sử dụng bashism , do đó không có nội dung 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

Định dạng, sử dụng rẽ nhánh 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 một ngã ba (quy trình con mới thực hiện công việc và trả về kết quả thông 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 ngã ba :

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

Nhưng điều này không dễ dàng để 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 các nhánh bên trong bằng 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

4
Các +=nhà điều hành cũng là nhanh hơn nhiều so với $a="$a$b"trong các thử nghiệm của tôi .. Mà làm cho ý nghĩa.
Matt

7
Câu trả lời này là tuyệt vời, nhưng tôi nghĩ rằng nó thiếu var=${var}.shví dụ từ các câu trả lời khác, rất hữu ích.
genorama

1
bashvỏ duy nhất với +=toán tử? Tôi muốn xem nó có đủ di động không
bảnh bao

1
@dashy không. Tôi chắc chắn không phải là vỏ duy nhất với +=toán tử, nhưng tất cả các cách này là bashism , vì vậy không thể 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

134

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

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh

4
Mặc dù không có ký tự đặc biệt, cũng không có khoảng trắng đượ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ô dụng: var=myscript;var=$var.sh;echo $varsẽ có hiệu ứng tương tự (Công việc này dưới bash, dash, busybox và các dấu khác).
F. Hauri

@ F.Hauri cảm ơn bạn đã chỉ ra điều đó. Nhưng nếu bạn nối thêm một số, nó sẽ không hoạt động: ví dụ: echo $var2không sản xuấtmyscript2
Pynchia

@Pynchia Công việc này vì dấu chấm .bất hợp pháp trong tên biến. Nếu khác echo ${var}2hoặc xem câu trả lời của tôi
F. Hauri

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

Sẽ xuất

helloohaikthxbye

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


3
Không hoạt động. Tôi nhận được "backupstorefolder: lệnh không tìm thấy" từ bash trong đó "backupstorefolder" là tên của một biến.
Zian Choy

7
Điều này giúp cú pháp làm nổi bật khá nhiều và loại bỏ một số sự mơ hồ của con người.
Ray Foss

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

     


10
Đây là câu trả lời hữu ích nhất cho shell scripting. Tôi đã tìm thấy chính mình trong 30 phút cuối cùng bởi vì tôi có một khoảng trống trước và sau dấu bằng !!
Stefan

8
foo = "$ {foo} World"
XXL

@XXL chắc chắn tôi muốn sử dụng dấu ngoặc để đóng gói tên của var. Rất khuyến khích
Sergio A.

33

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

Ví dụ, nếu bạn cố nối một chuỗi với một chuỗi khác,

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

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

Hello World

với một không gian thêm.

$aWorld

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

${a}World

sản xuất

HelloWorld

1
... do đó ${a}\ Worldtạo raHello World
XavierStuvw

Điều này làm tôi ngạc nhiên; Tôi đã dự kiến c=$a$bở đây sẽ làm điều tương tự như c=$a World(mà sẽ cố chạy Worldnhư một lệnh). Tôi đoán điều đó có nghĩa là bài tập được phân tích cú pháp trước khi các biến được mở rộng ..
mwfearnley

30

Dưới đây là một bản tóm tắt ngắn gọn về những gì hầu hết các câu trả lời đang nói về.

Giả sử chúng ta có hai biến và $ 1 được đặt thành 'một':

set one two
a=hello
b=world

Bảng dưới đây giải thích các bối cảnh khác nhau nơi chúng ta có thể kết hợp các giá trị abđể tạo một biến mới , 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

Một vài lưu ý:

  • kèm theo RHS của một bài tập trong dấu ngoặc kép nói chung là một cách thực hành tốt, mặc dù nó khá tùy chọn trong nhiều trường hợp
  • += sẽ tốt hơn từ quan điểm hiệu suất nếu một chuỗi lớn đang được xây dựng theo từng bước nhỏ, đặc biệt là trong một vòng lặp
  • sử dụng {}xung quanh tên biến để định hướng mở rộng của chúng (như trong hàng 2 trong bảng trên). Như đã thấy trên các hàng 3 và 4, không cần thiết {}trừ khi một biến được nối với một chuỗi bắt đầu bằng một ký tự là ký tự đầu tiên hợp lệ trong tên biến shell, đó là bảng chữ cái hoặc dấu gạch dưới.

Xem thêm:


2
Nếu bạn lo lắng về hiệu suất, hãy xem phân tích trong câu trả lời của tôi stackoverflow.com/a/47878161/117471
Bruno Bronosky

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

20

Một cách tiếp cận khác ...

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

... và còn một cái nữa.

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

1
Đó là những gì tôi đã làm, và tôi thấy nó rất đơn giản và dễ hiểu hơn những câu trả lời khác. Có một lý do không ai trong các câu trả lời được bình chọn nhiều nhất chỉ ra tùy chọn này?
quimnuss

1
@quimnuss Thực tế các chuỗi không khớp với các chuỗi được sử dụng trong câu hỏi OP có thể là một lý do chính đáng.
jlliagre

20

Nếu bạn muốn nối thêm một cái gì đó như dấu gạch dưới, hãy sử dụng esc (\)

FILEPATH=/opt/myfile

Điều này không hoạt động:

echo $FILEPATH_$DATEX

Điều này hoạt động tốt:

echo $FILEPATH\\_$DATEX

11
Hoặc cách khác, $ {FILEPATH} _ $ DATEX. Ở đây {} được sử dụng để chỉ ra ranh giới của tên biến. Điều này là phù hợp bởi vì dấu gạch dưới là một ký tự hợp pháp trong các tên biến, vì vậy, trong bash đoạn trích của bạn thực sự cố gắng giải quyết FILEPATH_, không chỉ $ FILEPATH
Nik O'Lai

1
đối với tôi, tôi có một biến là $ var1 và hằng số bên cạnh này, vì vậy echo $ var1_costant_traling_part hoạt động với tôi
YouAreAwemme

2
Tôi đoán người ta chỉ cần một phản ứng dữ dội để trốn thoát: echo $a\_$bsẽ làm. Như được gợi ý trong nhận xét của Nik O'Lai, gạch dưới là một nhân vật bình thường. Việc xử lý các khoảng trắng nhạy hơn nhiều đối với các chuỗi, tiếng vang và nối --- người ta có thể sử dụng \ và đọc kỹ chủ đề này vì vấn đề này trở lại ngay bây giờ và sau đó.
XavierStuvw

16

Cách đơn giản nhất với dấu ngoặc kép:

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

1
Quá nhiều dấu ngoặc kép, IMHO. var=$B$b"a"; echo Hello\ $vartôi sẽ làm, tôi tin
XavierStuvw

Tôi đề nghị sử dụng tất cả các dấu ngoặc kép, vì nếu bạn đặt nó ở mọi nơi bạn không thể bỏ lỡ, bạn không phải suy nghĩ.
betontalpfa

15

Bạn có thể nối mà không có dấu ngoặc kép. Đây là một ví dụ:

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

Tuyên bố cuối cùng này sẽ in "OpenSystems" (không có dấu ngoặc kép).

Đây là một ví dụ về tập lệnh Bash:

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

1
Cú pháp của khối đầu tiên là khó hiểu. Những dấu $ này có ý nghĩa gì?
XavierStuvw

15

Ngay cả khi toán tử + = hiện được phép, nó đã được giới thiệu trong Bash 3.1 năm 2004.

Bất kỳ tập lệnh nào sử dụng toán tử này trên các phiên bản Bash cũ hơn sẽ không thành công với lỗi "không tìm thấy lệnh" nếu bạn may mắn hoặc "lỗi cú pháp gần mã thông báo không mong muốn".

Đối với những người quan tâm đến khả năng tương thích ngược, hãy sử dụng các phương pháp nối Bash tiêu chuẩn cũ hơn, giống như các phương pháp được đề cập trong câu trả lời đã chọn:

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

1
Cảm ơn bạn đã chỉ ra điều này, tôi chỉ tìm kiếm phiên bản nào cần thiết để hoạt động.
Rho Phi

14

Tôi thích sử dụng dấu ngoặc nhọn ${}để mở rộng biến trong chuỗi:

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

Dấu ngoặc nhọn sẽ phù hợp với việc sử dụng chuỗi liên tục:

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

Nếu không sử dụng foo = "$fooWorld"sẽ không hoạt động.


8

Nếu những gì bạn đang cố gắng làm là chia một chuỗi thành nhiều dòng, bạn có thể sử dụng dấu gạch chéo ngược:

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

Với một khoảng trống ở giữa:

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

Điều này cũng chỉ thêm một không gian ở giữa:

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

Tôi sợ đây không phải là ý của nó
installero

7

Cách an toàn hơn:

a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD

Các chuỗi chứa khoảng trắng có thể trở thành một phần của lệnh, sử dụng "$ XXX" và "$ {XXX}" để tránh các lỗi này.

Ngoài ra, hãy xem câu trả lời khác về + =


Điểm của các chuỗi có khoảng trắng được đọc dưới dạng lệnh hiển thị tại điểm định nghĩa. Vì vậy, d=DD DDsẽ cung cấp cho DD: command not found--- lưu ý rằng đó là DD cuối cùng, chứ không phải là không tìm thấy. Nếu tất cả các toán hạng được định dạng chính xác và đã chứa các khoảng trắng cần thiết, bạn có thể chỉ cần ghép nối với s=${a}${b}${c}${d}; echo $s, với ít dấu ngoặc kép hơn. Ngoài ra, bạn có thể sử dụng \ (khoảng trắng thoát) để tránh những vấn đề này --- d=echo\ echosẽ không khởi chạy bất kỳ lời gọi tiếng vang nào, trong khi đó d=echo echosẽ.
XavierStuvw

7

Có một trường hợp cụ thể mà bạn nên quan tâm:

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

Sẽ đầu ra "daniel"san, và không danielsan, như bạn có thể muốn. Trong trường hợp này, bạn nên làm thay thế:

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

6
a="Hello,"
a=$a" World!"
echo $a

Đây là cách bạn nối hai chuỗi.


1
Điều này hoạt động, nhưng đôi khi nó sẽ mang lại kết quả không thể đoán trước vì nội suy biến không được bảo vệ. Vì vậy, bạn không thể dựa vào mẫu này cho tất cả các trường hợp sử dụng.
Anthony Rutledge

5

Nếu nó là ví dụ của bạn về việc thêm " World"vào chuỗi gốc, thì nó có thể là:

#!/bin/bash

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

Đầu ra:

Hello World

5
var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3

2
Cũng var3=$var1\ $var2có tác dụng tương tự
XavierStuvw

5

Có những lo ngại về hiệu suất, nhưng không có dữ liệu được cung cấp. Hãy để tôi đề nghị một bài kiểm tra đơn giản.

(GHI CHÚ: date trên macOS không cung cấp nano giây, vì vậy điều này phải được thực hiện trên Linux.)

Tôi đã tạo append_test.sh trên GitHub với nội dung:

#!/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

Kiểm tra 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

Bài kiểm tra 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

Các lỗi chỉ ra rằng Bash của tôi đã lên tới 335.54432 MB trước khi nó bị hỏng. Bạn có thể thay đổi từ nhân đôi dữ liệu sang nối thêm hằng số để có được biểu đồ chi tiết hơn và điểm thất bại. Nhưng tôi nghĩ điều này sẽ cung cấp cho bạn đủ thông tin để quyết định xem bạn có quan tâm hay không. Cá nhân, dưới 100 MB tôi không. Số dặm của bạn có thể thay đổi.


Hấp dẫn! Hãy xem xét: 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"(Hãy thử điều này trên máy chủ không hiệu quả !!;)
F. Hauri

4

Tôi muốn xây dựng một chuỗi từ một danh sách. Không thể tìm thấy câu trả lời cho điều đó vì vậy tôi đăng nó ở đây. Đây là những gì tôi đã làm:

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

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

echo ${string}

và sau đó tôi nhận được đầu ra sau đây:

1 2 3 4 5

4

Mặc dù có toán tử đặc biệt +=, để ghép nối, có một cách đơn giản hơn để đi:

foo='Hello'
foo=$foo' World'
echo $foo

Báo giá kép mất thêm một thời gian tính toán để giải thích các biến bên trong. Tránh nó nếu có thể.


3

Lưu ý rằng điều này sẽ không hoạt động

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

vì nó dường như giảm $ foo và để lại cho bạn:

PREFIX_WORLD

nhưng điều này sẽ làm việc:

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

và để lại cho bạn đầu ra chính xác:

PREFIX_HELLO_WORLD


8
điều này xảy ra bởi vì dấu gạch dưới là ký tự hợp lệ trong các tên biến, vì vậy bash xem foo_ là một biến. Khi cần phải nói với bash ranh giới tên var chính xác, có thể sử dụng dấu ngoặc nhọn: PREFIX _ $ {foo} _ $ bar
Nik O'Lai

2

Đây là một trong những thông qua AWK :

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

1
Thật tuyệt, nhưng tôi nghĩ rằng tôi có thể có được độ chính xác cao hơn bằng cách sử dụng Python!
kỹ thuật

1

Tôi làm theo cách này khi thuận tiện: Sử dụng lệnh nội tuyến!

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

1
Trên dòng đầu tiên, bạn có thể thả một ngã ba bằng cách sử dụng : date "+The current time is %a %b %d %Y +%T", thay vì echo ...$(date). Theo bash gần đây, bạn có thể viết : printf "The current time is %(%a %b %d %Y +%T)T\n" -1.
F. Hauri

1

Theo tôi, cách đơn giản nhất để nối hai chuỗi là viết một hàm thực hiện nó cho bạn, sau đó sử dụng hàm đó.

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

Tôi giống như làm một chức năng nhanh chóng.

#! /bin/sh -f
function combo() {
    echo $@
}

echo $(combo 'foo''bar')

Một cách khác để lột da một con mèo. Lần này với các chức năng: D


Gọi một hàm, cũng vậy trong một lớp con, là quá nhiều cho một concat đơn giản.
codeforester

-1

Tôi chưa biết về PHP, nhưng điều này hoạt động trong Linux Bash. Nếu bạn không muốn ảnh hưởng đến nó đến một biến, bạn có thể thử điều này:

read pp;  *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;

>Hello World!

Bạn có thể đặt một biến khác thay vì 'Xin chào' hoặc '!'. Bạn cũng có thể nối nhiều chuỗi hơn.


2
Sử dụng một subshell để thực hiện một cách ghép đơn giản là quá tốn kém!
tiền mã hóa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.