Jak połączyć zmienne łańcuchowe w Bash


2765

W PHP łańcuchy są łączone razem w następujący sposób:

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

Tutaj $foostaje się „Hello World”.

Jak to się robi w Bash?


6
foo="Hello" foo=$foo" World" echo $foo działało to raczej dla „#! / bin / sh”
parasrish

1
Co zrobić, jeśli chcesz HelloWorld bez miejsca?
Adi

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

spacje mają znaczenie w bash)
Capibar

Odpowiedzi:


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

Ogólnie rzecz biorąc, aby połączyć dwie zmienne, możesz po prostu zapisać je jedna po drugiej:

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

314
Prawdopodobnie dobrze jest przyzwyczaić się do wstawiania $foopodwójnych cudzysłowów, w czasach, gdy naprawdę ma to znaczenie.
Cascabel,

104
Nauczono nas, aby zawsze tak postępować, ponieważ gdy nastąpi podstawienie, spacje będą ignorowane przez powłokę, ale podwójne cudzysłowy zawsze będą chronić te spacje.
Strawberry

62
Czy w twoim pierwszym przykładzie musi być miejsce? Czy można zrobić coś takiego foo="$fooworld"? Zakładałbym, że nie ...
nonsens,

341
@nonsensickle To szukałoby zmiennej o nazwie fooworld. Ujednoznacznienie odbywa się za pomocą nawiasów klamrowych, jak w foo="${foo}world"...
twalberg

4
@ JVE999 Tak, to również działa, chociaż moim zdaniem nie jest tak dobre dla przejrzystości kodu ... Ale to może być tylko moja preferencja ... Istnieje kilka innych sposobów, aby to zrobić - chodzi o to, że upewniając się, że nazwa zmiennej jest oddzielona od części o nazwie innej niż zmienna, aby poprawnie przeanalizować.
twalberg,

1127

Bash obsługuje również +=operatora, jak pokazano w tym kodzie:

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

2
Czy mogę użyć tej składni ze słowem kluczowym eksportu? np. export A+="Z"a może Azmienną trzeba wyeksportować tylko raz?
levesque

3
@levesque: Both :-). Zmienne należy wyeksportować tylko raz, ale export A+=Zdziała również całkiem nieźle.
thkala

38
Ponieważ jest to bashizm, myślę, że warto wspomnieć, że nigdy nie powinieneś używać #!/bin/shw skrypcie używającym tej konstrukcji.
Score_Under

2
Jest to konkretny i tylko operator plus-równy. To znaczy, w przeciwieństwie do Javascript, w Bash, echo $ A + $ B drukuje „X Y + Z”
phpguru

6
Bashism to funkcja powłoki, która jest obsługiwana tylko w bashniektórych bardziej zaawansowanych powłokach. Nie będzie działał pod busybox shlub dash(który jest /bin/shna wielu dystrybucjach), ani z niektórymi innymi powłokami, takimi jak /bin/shdostarczone we FreeBSD.
Score_Under

960

Najpierw uderz

Ponieważ pytanie dotyczy konkretnie Basha , moja pierwsza część odpowiedzi przedstawiłaby różne sposoby właściwego wykonania tego:

+=: Dołącz do zmiennej

Składni +=można używać na różne sposoby:

Dołącz do ciągu var+=...

(Ponieważ jestem oszczędny, użyję tylko dwie zmienne fooi a, a następnie ponownie użyć tego samego w całej odpowiedź. ;-)

a=2
a+=4
echo $a
24

Używając składni pytania Przepełnienie stosu ,

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

działa w porządku!

Dołącz do liczby całkowitej ((var+=...))

zmienna ajest ciągiem, ale także liczbą całkowitą

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

Dołącz do tablicy var+=(...)

Nasz ajest również tablicą tylko jednego elementu.

echo ${a[@]}
36

a+=(18)

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

Zauważ, że między nawiasami znajduje się tablica oddzielona spacjami . Jeśli chcesz zapisać ciąg zawierający spacje w tablicy, musisz je zawrzeć:

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

Hmm .. to nie jest błąd, ale funkcja ... Aby zapobiec bashowi, aby spróbować się rozwinąć !", możesz:

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: Ponownie konstruuj zmienną za pomocą wbudowanego polecenia

printf Wbudowane polecenie daje potężny sposób rysunek format string. Ponieważ jest to wbudowany Bash , istnieje możliwość wysłania sformatowanego ciągu do zmiennej zamiast drukowania na stdout:

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

W tej tablicy jest siedem ciągów . Więc możemy zbudować sformatowany ciąg zawierający dokładnie siedem argumentów pozycyjnych:

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

Lub możemy użyć jednego ciągu formatu argumentu, który będzie powtarzany przy liczbie przesłanych argumentów ...

Zauważ, że nasza awciąż jest tablicą! Zmienia się tylko pierwszy element!

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

W bash, kiedy uzyskujesz dostęp do nazwy zmiennej bez określania indeksu, zawsze adresujesz tylko pierwszy element!

Aby pobrać naszą tablicę siedmiu pól, wystarczy ponownie ustawić pierwszy element:

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

Ciąg formatu jednego argumentu z wieloma argumentami przekazanymi do:

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

Korzystanie ze składni pytania Przepełnienie stosu :

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

Nota: Zastosowanie podwójnych cudzysłowach mogą być użyteczne do manipulowania ciągi, które zawierają spaces, tabulationsi / lubnewlines

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

Shell teraz

Pod powłoką POSIX nie można było używać bashism , więc nie ma wbudowanego printf .

Gruntownie

Ale możesz po prostu zrobić:

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

Sformatowane przy użyciu rozwidlenia printf

Jeśli chcesz użyć bardziej wyrafinowanych konstrukcji, musisz użyć widelca (nowy proces potomny, który wykona zadanie i zwróci wynik stdout):

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

Historycznie można było użyć backicks do pobrania wyniku rozwidlenia :

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

Nie jest to jednak łatwe do zagnieżdżenia :

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

z backtickami musisz uciec wewnętrznym widelcem z backslashes :

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

4
+=Operator jest również o wiele szybciej niż $a="$a$b"w moich testach .. Który ma sens.
Matt

7
Ta odpowiedź jest niesamowita, ale myślę, że brakuje jej var=${var}.shprzykładu z innych odpowiedzi, co jest bardzo przydatne.
genorama,

1
Czy bashjedyna powłoka z +=operatorem? Chcę się przekonać, czy jest wystarczająco przenośny
dashy

1
@dashesy no. z pewnością nie jest to jedyna powłoka z +=operatorem, ale wszystkie te sposoby to bashizmy , więc nie przenośne! Nawet ty możesz napotkać specjalny błąd w przypadku niewłaściwej wersji bash!
F. Hauri

134

Możesz to również zrobić:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh

4
Chociaż nie są używane żadne specjalne znaki, ani spacje, podwójne cudzysłowy, cudzysłowy i nawiasy klamrowe są bezużyteczne: var=myscript;var=$var.sh;echo $varmiałyby takie same efekty (Działa w trybie bash, myślnik, busybox i innych).
F. Hauri

@ F.Hauri dziękuję za zwrócenie na to uwagi. Ale gdybyś dołączył liczbę, nie zadziałałoby: np. echo $var2Nie produkujemyscript2
Pynchia

@Pynchia Działa z powodu .niedozwolonej kropki w nazwie zmiennej. Jeśli jeszcze echo ${var}2lub zobacz moją odpowiedź
F. Hauri

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

Wyjdzie

helloohaikthxbye

Jest to przydatne, gdy $blaohai prowadzi do błędu nie znaleziono zmiennej. Lub jeśli masz ciągi znaków lub inne znaki specjalne. "${foo}"właściwie ucieka przed wszystkim, co do niego włożysz.


3
Nie działa Dostaję „backupstorefolder: polecenie nie znaleziono” z bash, gdzie „backupstorefolder” jest nazwą zmiennej.
Zian Choy,

7
Pomaga to w dość dużym podświetlaniu składni i usuwa pewne ludzkie dwuznaczności.
Ray Foss,

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

     


10
Jest to najbardziej przydatna odpowiedź na skrypty powłoki. Znalazłem się w ciągu ostatnich 30 minut, ponieważ miałem wolne miejsce przed i po znaku równości !!
Stefan

8
foo = "$ {foo} Świat"
XXL

@XXL na pewno wolałbym używać nawiasów do enkapsulacji nazwy var. Gorąco polecam
Sergio A.

33

Sposób, w jaki rozwiązałem problem, jest po prostu

$a$b

Na przykład,

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

który produkuje

Hello World

Jeśli na przykład spróbujesz połączyć łańcuch z innym łańcuchem,

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

wtedy echo "$c"wyprodukuje

Hello World

z dodatkową przestrzenią.

$aWorld

nie działa, jak możesz sobie wyobrazić, ale

${a}World

produkuje

HelloWorld

1
... stąd ${a}\ WorldprodukujeHello World
XavierStuvw

To mnie zaskakuje; Spodziewałbym się c=$a$btutaj, że zrobię to samo, co c=$a World(które spróbuje uruchomić Worldjako polecenie). To chyba oznacza, że ​​przypisanie jest analizowane przed rozwinięciem zmiennych.
mwfearnley,

30

Oto zwięzłe podsumowanie tego, o czym mówi większość odpowiedzi.

Powiedzmy, że mamy dwie zmienne, a 1 $ jest ustawiony na „jeden”:

set one two
a=hello
b=world

Poniższa tabela wyjaśnia różne konteksty, gdzie możemy połączyć z wartościami ai baby utworzyć nową zmienną, 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

Kilka uwag:

  • zawarcie RHS zadania w podwójnych cudzysłowach jest ogólnie dobrą praktyką, choć w wielu przypadkach jest dość opcjonalne
  • += jest lepszy z punktu widzenia wydajności, jeśli duży ciąg jest budowany małymi przyrostami, szczególnie w pętli
  • użyj {}wokół nazw zmiennych, aby ujednoznacznić ich rozwinięcie (jak w wierszu 2 w powyższej tabeli). Jak widać w wierszach 3 i 4, nie ma potrzeby, {}chyba że zmienna jest łączona z łańcuchem rozpoczynającym się od znaku, który jest prawidłowym pierwszym znakiem w nazwie zmiennej powłoki, czyli alfabet lub podkreślnik.

Zobacz też:


2
Jeśli
martwisz się

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

20

Jeszcze inne podejście ...

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

... i jeszcze jeden.

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

1
Tak właśnie zrobiłem i uznałem to za o wiele prostsze i bardziej bezpośrednie niż inne odpowiedzi. Czy istnieje powód, dla którego nikt z najczęściej głosowanych odpowiedzi nie wskazał tej opcji?
quimnuss

1
@ quimnuss Fakt, że ciągi nie pasują do tych używanych w pytaniu OP, może być dobrym powodem.
jlliagre

20

Jeśli chcesz dołączyć coś w rodzaju podkreślenia, użyj klawisza Escape (\)

FILEPATH=/opt/myfile

To nie działa:

echo $FILEPATH_$DATEX

Działa to dobrze:

echo $FILEPATH\\_$DATEX

11
Lub alternatywnie $ {FILEPATH} _ $ DATEX. Tutaj {} służą do wskazania granic nazwy zmiennej. Jest to odpowiednie, ponieważ znak podkreślenia jest prawną postacią w nazwach zmiennych, więc w twoim fragmencie bash faktycznie próbuje rozwiązać FILEPATH_, a nie tylko $ FILEPATH
Nik O'Lai

1
dla mnie miałem jedną zmienną tj. $ var1 i stałą obok tego, więc echo $ var1_costant_traling_part działa dla mnie
YouAreAwesome

2
Wydaje mi się, że do ucieczki wystarczy jeden luz echo $a\_$b. Jak wskazano w komentarzu Nik O'Lai, podkreślenie jest regularną postacią. Obsługa białych znaków jest znacznie bardziej wrażliwa na ciągi znaków, echo i konkatenację - można używać \ tego wątku i czytać go dokładnie, ponieważ ten problem pojawia się od czasu do czasu.
XavierStuvw

16

Najprostszy sposób ze znakami cudzysłowu:

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

1
Zbyt wiele znaków cudzysłowu, IMHO. var=$B$b"a"; echo Hello\ $varzrobiłbym, wierzę
XavierStuvw

Sugeruję użycie wszystkich znaków cudzysłowu, ponieważ jeśli umieścisz go wszędzie, gdzie nie możesz przegapić, nie będziesz musiał myśleć.
betontalpfa

15

Możesz konkatenować bez cudzysłowów. Oto przykład:

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

Ta ostatnia instrukcja wypisze „OpenSystems” (bez cudzysłowów).

To jest przykład skryptu Bash:

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

1
Składnia pierwszego bloku jest myląca. Co oznaczają te znaki $?
XavierStuvw

15

Nawet jeśli operator + = jest teraz dozwolony, został wprowadzony w wersji Bash 3.1 w 2004 roku.

Każdy skrypt używający tego operatora w starszych wersjach Bash nie powiedzie się z błędem „nie znaleziono polecenia”, jeśli masz szczęście lub „błędem składniowym w pobliżu nieoczekiwanego tokena”.

Dla tych, którym zależy na kompatybilności wstecznej, trzymaj się starszych standardowych metod konkatenacji Basha, takich jak te wymienione w wybranej odpowiedzi:

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

1
Dzięki za wskazanie tego, właśnie szukałem, która wersja jest wymagana, aby to zadziałało.
Rho Phi

14

Wolę używać nawiasów klamrowych ${}do rozwijania zmiennej w łańcuchu:

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

Nawiasy klamrowe będą pasować do ciągłego użycia sznurka:

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

W przeciwnym razie korzystanie foo = "$fooWorld"nie będzie działać.


8

Jeśli próbujesz podzielić łańcuch na kilka linii, możesz użyć odwrotnego ukośnika:

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

Z jednym odstępem pomiędzy:

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

Ten dodaje również tylko jedną spację między:

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

Obawiam się, że nie o to chodziło
installero

7

Bezpieczniejszy sposób:

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

Ciągi zawierające spacje mogą stać się częścią polecenia, użyj „$ XXX” i „$ {XXX}”, aby uniknąć tych błędów.

Plus spójrz na inną odpowiedź na temat + =


Punkt ciągów ze spacją odczytywaną jako polecenie pojawia się w punkcie definicji. d=DD DDDałbym więc DD: command not found--- zauważ, że jest to ostatni DD, a raczej d, że nie został znaleziony. Jeśli wszystkie operandy są poprawnie sformatowane i zawierają już wymagane spacje, możesz po prostu połączyć je s=${a}${b}${c}${d}; echo $sz mniejszymi znakami cudzysłowu. Możesz także użyć \ (klawisz Escape), aby uniknąć tych problemów --- d=echo\ echonie uruchomi żadnego wywołania echa, podczas gdy d=echo echobędzie.
XavierStuvw

7

Jest jeden szczególny przypadek, w którym powinieneś zachować ostrożność:

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

Wyjdzie "daniel"san, a nie danielsantak, jak mogłeś chcieć. W takim przypadku powinieneś zamiast tego zrobić:

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

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

W ten sposób łączysz dwa łańcuchy.


1
Działa to, ale czasami daje nieprzewidywalne wyniki, ponieważ interpolacja zmiennych nie jest chroniona. Dlatego nie możesz polegać na tym formularzu we wszystkich przypadkach użycia.
Anthony Rutledge

5

Jeśli jest to przykład dodawania " World"do oryginalnego ciągu znaków, może to być:

#!/bin/bash

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

Wyjście:

Hello World

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

2
var3=$var1\ $var2Ma również ten sam efekt
XavierStuvw

5

Istnieją obawy dotyczące wydajności, ale dane nie są oferowane. Pozwól, że zasugeruję prosty test.

(UWAGA: datew systemie macOS nie oferuje nanosekund, więc należy to zrobić w systemie Linux).

Utworzyłem append_test.sh na GitHub z zawartością:

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

Błędy wskazują, że mój Bash dostał się do 335,54432 MB, zanim się zawiesił . Możesz zmienić kod z podwojenia danych na dodawanie stałej, aby uzyskać bardziej szczegółowy wykres i punkt awarii. Ale myślę, że powinno to dać ci wystarczającą ilość informacji, aby zdecydować, czy cię to obchodzi. Osobiście poniżej 100 MB nie. Twój przebieg może się różnić.


Ciekawy! Zastanów się: 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"(Spróbuj tego na nieproduktywnym gospodarzu !!;)
F. Hauri

4

Chciałem zbudować ciąg z listy. Nie mogłem znaleźć na to odpowiedzi, więc opublikowałem ją tutaj. Oto co zrobiłem:

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

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

echo ${string}

a następnie otrzymuję następujące dane wyjściowe:

1 2 3 4 5

4

Pomimo specjalnego operatora, +=w przypadku konkatenacji istnieje prostszy sposób:

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

Podwójne cudzysłowy wymagają dodatkowego czasu obliczeniowego na interpretację zmiennych wewnątrz. Unikaj tego, jeśli to możliwe.


3

Pamiętaj, że to nie zadziała

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

wydaje się, że upuszcza $ foo i pozostawia:

PREFIX_WORLD

ale to zadziała:

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

i zostawić prawidłowe wyjście:

PREFIX_HELLO_WORLD


8
dzieje się tak, ponieważ znak podkreślenia jest poprawnym znakiem w nazwach zmiennych, więc bash widzi foo_ jako zmienną. Kiedy trzeba powiedzieć Bashowi dokładne granice nazwy var, można użyć nawiasów klamrowych: PREFIX _ $ {foo} _ $ bar
Nik O'Lai

2

Oto jeden z AWK :

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

1
Fajnie, ale myślę, że mógłbym uzyskać większą precyzję, używając Pythona!
techno

1

Robię to w wygodny sposób: użyj polecenia wbudowanego!

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

1
W 1. linii możesz upuścić widelec , używając: date "+The current time is %a %b %d %Y +%T"zamiast echo ...$(date). Zgodnie z niedawnym bash, można napisać: printf "The current time is %(%a %b %d %Y +%T)T\n" -1.
F. Hauri

1

Moim zdaniem najprostszym sposobem na połączenie dwóch łańcuchów jest napisanie funkcji, która zrobi to za Ciebie, a następnie użycie tej funkcji.

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

Lubię tworzyć szybką funkcję.

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

echo $(combo 'foo''bar')

Jeszcze inny sposób na skórowanie kota. Tym razem z funkcjami: D


Wywołanie funkcji, która również w podpowłoce, jest zbyt dużym przesadą dla prostego konkat.
codeforester,

-1

Nie wiem jeszcze o PHP, ale działa to w Linux Bash. Jeśli nie chcesz wpływać na zmienną, możesz spróbować:

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

>Hello World!

Możesz umieścić inną zmienną zamiast „Witaj” lub „!”. Możesz także połączyć więcej łańcuchów.


2
Użycie podpowłoki do wykonania prostej konkatenacji jest zbyt drogie!
codeforester
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.