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


W PHP ciągi są łączone razem w następujący sposób:

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

Tutaj, $foo staje się "Hello World".

Jak to się dzieje w Bash?


2102
2017-11-15 05:38


pochodzenie


foo="Hello"  foo=$foo" World"  echo $foo      to działało raczej dla "#! / bin / sh" - parasrish
Co zrobić, jeśli chcesz HelloWorld bez miejsca? - Adi


Odpowiedzi:


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
> helloworld

2852
2017-11-15 05:41



Prawdopodobnie dobrze, aby nabrać zwyczaju stawiania $foo wewnątrz podwójnych cytatów, za czasy, kiedy to naprawdę ma znaczenie. - Cascabel
Nauczono nas, abyśmy zawsze to robili, ponieważ gdy nastąpi podstawienie, przestrzenie będą ignorowane przez powłokę, ale podwójne cudzysłowy zawsze będą chronić te przestrzenie. - Strawberry
Czy w twoim pierwszym przykładzie musi być miejsce? Czy można coś takiego zrobić? foo="$fooworld"? Zakładam, że nie ... - nonsensickle
@nonsensickle To by szukało zmiennej o nazwie fooworld. Ujednoznacznienie, które odbywa się za pomocą nawiasów klamrowych, jak w foo="${foo}world"... - twalberg
@ JVE999 Tak, to też działa, chociaż moim zdaniem nie jest tak dobre dla klarowności kodu ... Ale to może być moja preferencja ... Jest jeszcze kilka innych sposobów, w jakie można to zrobić - chodzi o to, upewniając się, że nazwa zmiennej jest oddzielona od części o niezmiennej nazwie, aby poprawnie analizować. - twalberg


Bash obsługuje także operator + =, jak pokazano w następującym transkrypcie:

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

939
2017-11-15 08:33



Jest to znacznie lepsze niż zaakceptowana odpowiedź, dziękuję! Dodano "dołącz" jako tag, aby ułatwić znalezienie tego pytania. - noamtm
Czy mogę użyć tej składni ze słowem kluczowym export? na przykład export A+="Z" lub może A zmienną należy wyeksportować tylko raz? - levesque
@levesque: Both :-). Zmienne należy wyeksportować tylko raz, ale export A+=Z działa całkiem nieźle. - thkala
Ponieważ jest to bashism, myślę, że warto wspomnieć, że nigdy nie powinieneś używać #!/bin/sh w skrypcie używającym tej konstrukcji. - Score_Under
Jest to konkretnie i tylko operator, który ma równe szanse. To znaczy, w przeciwieństwie do JavaScript, w Bash, echo $ A + $ B drukuje "X Y + Z" - phpguru


Najpierw Bash

Jako że to pytanie dotyczy konkretnie Grzmotnąć, moja pierwsza część odpowiedzi przedstawia różne sposoby robienia tego prawidłowo:

+=: Dołącz do zmiennej

Składnia += mogą być używane na różne sposoby:

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

(Ponieważ jestem oszczędny, użyję tylko dwóch zmiennych foo i a a następnie ponownie użyć tego samego w całej odpowiedzi. ;-)

a=2
a+=4
echo $a
24

Używając Pytanie dotyczące przepełnienia stosu składnia,

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

działa w porządku!

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

zmienna a jest łańcuchem, ale także liczbą całkowitą

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

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

Nasz a jest także 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ę oddzielona spacjami tablica. Jeśli chcesz przechowywać łańcuch zawierający spacje w tablicy, musisz je zamknąć:

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

Hmm .. to nie jest błąd, ale funkcja... Aby uniemożliwić bashowi rozwój !", mógłbyś:

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: Przebuduj zmienną za pomocą wbudowany dowództwo

The printf  wbudowany polecenie daje potężny sposób rysowania formatu ciągu. Ponieważ jest to Bash wbudowanyistnieje opcja wysyłania sformatowanego łańcucha do zmiennej zamiast drukowania stdout:

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

Tam jest siedem smyczki w tej tablicy. Tak 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ć jeden ciąg formatu argumentu które będą powtarzane, jak wiele argumentów złożonych ...

Zauważ, że nasz a wciąż jest tablicą! Tylko pierwszy element został zmieniony!

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, gdy uzyskujesz dostęp do nazwy zmiennej bez określania indeksu, zawsze adresujesz tylko pierwszy element!

Aby odzyskać naszą siedem tablic polowych, musimy tylko ponownie ustawić 1. 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 argumentów w jednym argumencie z wieloma argumentami przekazanymi do:

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

Używając Pytanie dotyczące przepełnienia stosu składnia:

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

Nota: użycie podwójne cytaty może być użyteczne do manipulowania napisami, które zawierają spaces, tabulations i / lub newlines

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

Teraz Shell

Pod POSIX powłoka, której nie można użyć baszty, więc nie ma wbudowany  printf.

Gruntownie

Ale możesz po prostu zrobić:

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

Sformatowany, używając rozwidlony  printf

Jeśli chcesz użyć bardziej wyrafinowanych konstrukcji, musisz użyć a widelec (nowy proces potomny, który wykonuje zadanie i zwraca wynik przez stdout):

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

Historycznie można użyć backticks do pobierania wyniku widelec:

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

Ale nie jest to łatwe zagnieżdżanie:

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

z backtiksem, musisz uciec wewnętrznymi widłami backslashes:

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



The += operator jest również znacznie szybszy niż $a="$a$b" w moich testach .. Co ma sens. - Matt
Ta odpowiedź jest niesamowita, ale myślę, że jej brakuje var=${var}.sh przykład z innych odpowiedzi, co jest bardzo przydatne. - geneorama
Jest bash jedyna powłoka z += operator? Chcę sprawdzić, czy jest wystarczająco przenośny - dashesy
@dashesy no. na pewno nie jest to jedyna powłoka += operatora, ale wszystkie te sposoby są baszty, więc nie przenośne! Nawet w przypadku niewłaściwej wersji bash możesz napotkać specjalny błąd! - F. Hauri


Możesz to również zrobić:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh

114
2017-10-28 03:09



Chociaż nie są używane żadne znaki specjalne ani spacje, podwójne cytaty, cytaty i nawiasy klamrowe są bezużyteczne: var=myscript;var=$var.sh;echo $var miałby takie same efekty (Ta praca pod bash, dash, busybox i inne). - F. Hauri


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

Wytworzy wynik

helloohaikthxbye

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


103
2017-07-25 15:48



Nie działa. Otrzymuję "backupstorefolder: command not found" z basha, gdzie "backupstorefolder" jest nazwą zmiennej. - Zian Choy
Pomaga to w znacznym podświetleniu składni i usuwa pewne ludzkie niejasności. - Ray Foss


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


35
2017-11-15 05:44



Jest to najbardziej przydatna odpowiedź na skrypty powłoki. Znalazłem się przez ostatnie 30 minut, ponieważ miałem miejsce przed i po znaku równości !! - Stefan
foo = "$ {foo} Świat" - XXL


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 spróbujesz połączyć ciąg z innym ciągiem, na przykład

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

następnie echo "$c" będzie produkować

Hello World

z dodatkową przestrzenią.

$aWorld

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

${a}World

produkuje

HelloWorld

29
2018-03-07 16:43



...stąd ${a}\ World produkuje Hello World - XavierStuvw