In PHP werden Zeichenfolgen wie folgt miteinander verknüpft:
$foo = "Hello";
$foo .= " World";
Hier $foo
wird "Hallo Welt".
Wie wird dies in Bash erreicht?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
In PHP werden Zeichenfolgen wie folgt miteinander verknüpft:
$foo = "Hello";
$foo .= " World";
Hier $foo
wird "Hallo Welt".
Wie wird dies in Bash erreicht?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
Antworten:
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
Um zwei Variablen zu verketten, können Sie sie im Allgemeinen einfach nacheinander schreiben:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
$foo
doppelte Anführungszeichen zu setzen, für die Zeiten, in denen es wirklich wichtig ist.
foo="$fooworld"
? Ich würde nicht annehmen ...
fooworld
. Disambiguierung, dass mit Klammern gemacht wird, wie in foo="${foo}world"
...
Bash unterstützt auch einen +=
Operator, wie in diesem Code gezeigt:
$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
export A+="Z"
oder muss die A
Variable nur einmal exportiert werden?
export A+=Z
funktionieren aber auch ganz gut.
#!/bin/sh
in einem Skript verwenden sollten, das diese Konstruktion verwendet.
bash
und einigen anderen fortgeschritteneren Shells unterstützt wird. Es funktioniert nicht unter busybox sh
oder dash
(was /bin/sh
in vielen Distributionen der Fall ist) oder bestimmten anderen Shells wie den /bin/sh
auf FreeBSD bereitgestellten.
Da diese Frage speziell für Bash steht , würde mein erster Teil der Antwort verschiedene Möglichkeiten aufzeigen, dies richtig zu machen:
+=
: An Variable anhängenDie Syntax +=
kann auf verschiedene Arten verwendet werden:
var+=...
(Weil ich sparsam bin, werde ich nur zwei Variablen verwenden foo
und a
dann wieder verwenden das gleiche in der ganzen Antwort. ;-)
a=2
a+=4
echo $a
24
Verwenden der Stack Overflow- Fragensyntax:
foo="Hello"
foo+=" World"
echo $foo
Hello World
funktioniert gut!
((var+=...))
Variable a
ist eine Zeichenfolge, aber auch eine Ganzzahl
echo $a
24
((a+=12))
echo $a
36
var+=(...)
Unser a
ist auch eine Reihe von nur einem Element.
echo ${a[@]}
36
a+=(18)
echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18
Beachten Sie, dass zwischen Klammern ein durch Leerzeichen getrenntes Array steht . Wenn Sie eine Zeichenfolge mit Leerzeichen in Ihrem Array speichern möchten, müssen Sie diese einschließen:
a+=(one word "hello world!" )
bash: !": event not found
Hmm .. das ist kein Fehler, sondern eine Funktion ... Um zu verhindern, dass Bash versucht, sich zu entwickeln !"
, könnten Sie:
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
: Variable mit dem eingebauten Befehl neu erstellenDer printf
eingebaute Befehl bietet eine leistungsstarke Möglichkeit zum Zeichnen des Zeichenfolgenformats. Da dies ein eingebauter Bash ist , gibt es eine Option zum Senden einer formatierten Zeichenfolge an eine Variable, anstatt auf Folgendes zu drucken stdout
:
echo ${a[@]}
36 18 one word hello world! hello world! hello world!
Dieses Array enthält sieben Zeichenfolgen . Wir könnten also eine formatierte Zeichenfolge erstellen, die genau sieben Positionsargumente enthält:
printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'
Oder wir könnten eine Zeichenfolge im Argumentformat verwenden, die wiederholt wird, sobald viele Argumente eingereicht wurden ...
Beachten Sie, dass unser a
Array immer noch ist! Nur das erste Element wird geändert!
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!")'
Wenn Sie unter bash auf einen Variablennamen zugreifen, ohne einen Index anzugeben, adressieren Sie immer nur das erste Element!
Um unser Array mit sieben Feldern abzurufen, müssen wir nur das erste Element zurücksetzen:
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!")'
Eine Zeichenfolge im Argumentformat mit vielen Argumenten, die übergeben werden an:
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
Hinweis: Die Verwendung von doppelten Anführungszeichen kann nützlich sein, um Zeichenfolgen zu bearbeiten spaces
, die tabulations
und / oder enthaltennewlines
printf -v foo "%s World" "$foo"
Unter der POSIX- Shell konnten Sie keine Bashismen verwenden , daher ist keine integrierte Funktion vorhanden printf
.
Aber Sie könnten einfach tun:
foo="Hello"
foo="$foo World"
echo $foo
Hello World
printf
Wenn Sie komplexere Konstruktionen verwenden möchten, müssen Sie einen Fork verwenden (neuer untergeordneter Prozess, der den Job erstellt und das Ergebnis über zurückgibt stdout
):
foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World
In der Vergangenheit konnten Sie Backticks zum Abrufen des Ergebnisses einer Gabelung verwenden :
foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World
Dies ist jedoch nicht einfach zum Verschachteln :
foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013
Mit Backticks müssen Sie den inneren Gabeln mit Backslashes entkommen :
foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013
+=
Bediener ist auch viel schneller als $a="$a$b"
in meinen Tests. Was Sinn macht.
var=${var}.sh
Beispiel in anderen Antworten, was sehr nützlich ist.
bash
die einzige Shell mit +=
Operator? Ich möchte sehen, ob es tragbar genug ist
+=
Operator, aber all diese Möglichkeiten sind Bashismen , also nicht tragbar! Sogar Sie könnten im Falle einer falschen Bash-Version auf einen besonderen Fehler stoßen!
Sie können dies auch tun:
$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh
var=myscript;var=$var.sh;echo $var
Dies hätte die gleichen Auswirkungen (dies funktioniert unter Bash, Dash, Busybox und anderen).
echo $var2
produziert nichtmyscript2
.
im Variablennamen unzulässig ist. Wenn sonst echo ${var}2
oder siehe meine Antwort
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"
Wird ausgegeben
helloohaikthxbye
Dies ist nützlich, wenn
$blaohai
ein Fehler mit einer Variablen nicht gefunden wird. Oder wenn Sie Leerzeichen oder andere Sonderzeichen in Ihren Zeichenfolgen haben. "${foo}"
entgeht alles, was Sie hineingesteckt haben.
foo="Hello "
foo="$foo World"
Die Art und Weise, wie ich das Problem lösen würde, ist gerecht
$a$b
Zum Beispiel,
a="Hello"
b=" World"
c=$a$b
echo "$c"
was produziert
Hello World
Wenn Sie versuchen, eine Zeichenfolge mit einer anderen Zeichenfolge zu verketten, z.
a="Hello"
c="$a World"
dann echo "$c"
wird produzieren
Hello World
mit einem zusätzlichen Platz.
$aWorld
funktioniert nicht, wie Sie sich vorstellen können, aber
${a}World
produziert
HelloWorld
${a}\ World
produziertHello World
c=$a$b
, dasselbe zu tun wie c=$a World
(was versuchen würde, World
als Befehl ausgeführt zu werden). Ich denke, das bedeutet, dass die Zuweisung analysiert wird, bevor die Variablen erweitert werden.
Hier ist eine kurze Zusammenfassung dessen, worüber die meisten Antworten sprechen.
Nehmen wir an, wir haben zwei Variablen und $ 1 wird auf 'eins' gesetzt:
set one two
a=hello
b=world
In der folgenden Tabelle werden die verschiedenen Kontexte erläutert, in denen wir die Werte von kombinieren a
und b
eine neue Variable erstellen können 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
Ein paar Anmerkungen:
+=
ist vom Standpunkt der Leistung aus besser, wenn eine große Zeichenfolge in kleinen Schritten erstellt wird, insbesondere in einer Schleife{}
um Variablennamen herum, um deren Erweiterung zu unterscheiden (wie in Zeile 2 in der obigen Tabelle). Wie in den Zeilen 3 und 4 zu sehen ist, ist dies nicht erforderlich, es sei {}
denn, eine Variable wird mit einer Zeichenfolge verknüpft, die mit einem Zeichen beginnt, das ein gültiges erstes Zeichen im Namen der Shell-Variablen ist, dh Alphabet oder Unterstrich.Siehe auch:
Noch ein Ansatz ...
> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.
... und noch eine.
> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
Wenn Sie so etwas wie einen Unterstrich anhängen möchten, verwenden Sie Escape (\).
FILEPATH=/opt/myfile
Das funktioniert nicht :
echo $FILEPATH_$DATEX
Das funktioniert gut:
echo $FILEPATH\\_$DATEX
echo $a\_$b
würde tun. Wie im Kommentar von Nik O'Lai angedeutet, ist der Unterstrich ein regulärer Charakter. Der Umgang mit Leerzeichen ist viel empfindlicher für Zeichenfolgen, Echo und Verkettung - man kann \
diesen Thread gründlich verwenden und lesen, da dieses Problem hin und wieder auftritt.
Der einfachste Weg mit Anführungszeichen:
B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
var=$B$b"a"; echo Hello\ $var
würde tun, ich glaube
Sie können ohne Anführungszeichen verketten. Hier ist ein Beispiel:
$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3
Diese letzte Anweisung würde "OpenSystems" (ohne Anführungszeichen) drucken.
Dies ist ein Beispiel für ein Bash-Skript:
v1=hello
v2=world
v3="$v1 $v2"
echo $v3 # Output: hello world
echo "$v3" # Output: hello world
Auch wenn der Operator + = jetzt zulässig ist, wurde er 2004 in Bash 3.1 eingeführt .
Jedes Skript, das diesen Operator in älteren Bash-Versionen verwendet, schlägt mit dem Fehler "Befehl nicht gefunden" fehl, wenn Sie Glück haben, oder mit einem "Syntaxfehler in der Nähe eines unerwarteten Tokens".
Wenn Sie sich für die Abwärtskompatibilität interessieren, sollten Sie sich an die älteren Standard-Bash-Verkettungsmethoden halten, wie sie in der ausgewählten Antwort erwähnt werden:
foo="Hello"
foo="$foo World"
echo $foo
> Hello World
Ich bevorzuge geschweifte Klammern ${}
zum Erweitern der Variablen in der Zeichenfolge:
foo="Hello"
foo="${foo} World"
echo $foo
> Hello World
Geschweifte Klammern passen zur kontinuierlichen Verwendung von Zeichenfolgen:
foo="Hello"
foo="${foo}World"
echo $foo
> HelloWorld
Andernfalls foo = "$fooWorld"
funktioniert die Verwendung nicht.
Wenn Sie versuchen, eine Zeichenfolge in mehrere Zeilen aufzuteilen , können Sie einen Backslash verwenden:
$ a="hello\
> world"
$ echo $a
helloworld
Mit einem Leerzeichen dazwischen:
$ a="hello \
> world"
$ echo $a
hello world
Dieser fügt auch nur ein Leerzeichen dazwischen hinzu:
$ a="hello \
> world"
$ echo $a
hello world
Sicherer Weg:
a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD
Zeichenfolgen, die Leerzeichen enthalten, können Teil des Befehls werden. Verwenden Sie "$ XXX" und "$ {XXX}", um diese Fehler zu vermeiden.
Schauen Sie sich auch eine andere Antwort zu + = an
d=DD DD
würde geben DD: command not found
--- beachten Sie, dass dies die letzte DD ist, eher d, die nicht gefunden wird. Wenn alle Operanden richtig formatiert sind und bereits die erforderlichen Leerzeichen enthalten, können Sie einfach s=${a}${b}${c}${d}; echo $s
mit weniger Anführungszeichen verketten . Sie können auch \
(maskiertes Leerzeichen) verwenden, um diese Probleme zu vermeiden. d=echo\ echo
Wird keinen Echoaufruf starten, wohingegen dies der d=echo echo
Fall ist.
Es gibt einen besonderen Fall, in dem Sie aufpassen sollten:
user=daniel
cat > output.file << EOF
"$user"san
EOF
Wird ausgegeben "daniel"san
und nicht danielsan
, wie Sie vielleicht wollten. In diesem Fall sollten Sie stattdessen Folgendes tun:
user=daniel
cat > output.file << EOF
${user}san
EOF
a="Hello,"
a=$a" World!"
echo $a
So verketten Sie zwei Zeichenfolgen.
Wenn dies Ihr Beispiel für das Hinzufügen " World"
zur ursprünglichen Zeichenfolge ist, kann es sein:
#!/bin/bash
foo="Hello"
foo=$foo" World"
echo $foo
Die Ausgabe:
Hello World
Es gibt Bedenken hinsichtlich der Leistung, es werden jedoch keine Daten angeboten. Lassen Sie mich einen einfachen Test vorschlagen.
(HINWEIS: Unter date
macOS werden keine Nanosekunden angeboten, daher muss dies unter Linux erfolgen.)
Ich habe append_test.sh auf GitHub mit dem Inhalt erstellt:
#!/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
Die Fehler zeigen an, dass mein Bash bis zu 335.54432 MB groß war, bevor er abstürzte. Sie können den Code von der Verdoppelung der Daten zum Anhängen einer Konstante ändern , um ein detaillierteres Diagramm und einen Fehlerpunkt zu erhalten. Aber ich denke, dies sollte Ihnen genügend Informationen geben, um zu entscheiden, ob Sie sich interessieren. Persönlich unter 100 MB tue ich das nicht. Ihr Kilometerstand kann variieren.
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"
(Versuchen Sie dies auf einem nicht produktiven Host !!;)
Ich wollte einen String aus einer Liste erstellen. Konnte keine Antwort darauf finden, also poste ich sie hier. Folgendes habe ich getan:
list=(1 2 3 4 5)
string=''
for elm in "${list[@]}"; do
string="${string} ${elm}"
done
echo ${string}
und dann bekomme ich folgende ausgabe:
1 2 3 4 5
Beachten Sie, dass dies nicht funktioniert
foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar
wie es scheint, $ foo fallen zu lassen und lässt Sie mit:
PREFIX_WORLD
aber das wird funktionieren:
foobar=PREFIX_"$foo"_"$bar"
und lassen Sie mit der richtigen Ausgabe:
PREFIX_HELLO_WORLD
Ich mache es so, wenn es Ihnen passt: Verwenden Sie einen Inline-Befehl!
echo "The current time is `date`"
echo "Current User: `echo $USER`"
date "+The current time is %a %b %d %Y +%T"
anstelle von verwenden echo ...$(date)
. Unter der letzten Bash könnten Sie schreiben : printf "The current time is %(%a %b %d %Y +%T)T\n" -1
.
Meiner Meinung nach besteht der einfachste Weg, zwei Zeichenfolgen zu verketten, darin, eine Funktion zu schreiben, die dies für Sie erledigt, und diese Funktion dann zu verwenden.
function concat ()
{
prefix=$1
suffix=$2
echo "${prefix}${suffix}"
}
foo="Super"
bar="man"
concat $foo $bar # Superman
alien=$(concat $foo $bar)
echo $alien # Superman
Ich mache gerne eine schnelle Funktion.
#! /bin/sh -f
function combo() {
echo $@
}
echo $(combo 'foo''bar')
Noch eine andere Art, eine Katze zu häuten. Diesmal mit Funktionen: D.
Ich weiß noch nichts über PHP, aber das funktioniert unter Linux Bash. Wenn Sie die Variable nicht beeinflussen möchten, können Sie Folgendes versuchen:
read pp; *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;
>Hello World!
Sie können anstelle von "Hallo" oder "!" Eine andere Variable einfügen. Sie können auch mehr Zeichenfolgen verketten.
foo="Hello"
foo=$foo" World"
echo $foo
Dies funktionierte eher für "#! / bin / sh"