risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come concatenare le variabili stringa in Bash

In PHP, le stringhe sono concatenate insieme come segue:

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

Qui, $foo diventa "Hello World".

Com'è fatto in Bash?

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

In generale per concatenare due variabili puoi semplicemente scriverle una dopo l'altra:

a='hello'
b='world'
c="$a$b"
echo $c
> helloworld
3285
codaddict

Bash supporta anche un operatore += come mostrato in questo codice:

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

Bash prima

Poiché questa domanda è specifica per Bash , la mia prima parte della risposta presenterebbe diversi modi per farlo correttamente:

+=: aggiungi alla variabile

La sintassi+=può essere utilizzata in diversi modi:

Aggiungi alla stringa var+=...

(Dato che sono parsimonioso, userò solo due variabili foo e a e quindi riutilizzerò lo stesso nell'intera risposta. ;-)

a=2
a+=4
echo $a
24

Utilizzando la sintassi della domanda Stack overflow,

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

funziona bene!

Aggiungi a un numero intero ((var+=...))

variable a è una stringa, ma anche un intero

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

Aggiungi a un array var+=(...)

Il nostro a è anche un array di un solo elemento.

echo ${a[@]}
36

a+=(18)

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

Si noti che tra parentesi, esiste un array spazio separato. Se si desidera memorizzare una stringa contenente spazi nell'array, è necessario includerli:

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

Hmm .. questo non è un bug, ma una funzione ... Per evitare che bash provi a sviluppare !", potresti:

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: ricostruisci la variabile usando il comando builtin

Il comando printfbuiltin offre un modo efficace per disegnare il formato della stringa. Poiché questo è un Bash builtin, c'è un'opzione per inviare una stringa formattata a una variabile invece di stampare su stdout:

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

Ci sono sette stringhe in questo array. Quindi potremmo costruire una stringa formattata contenente esattamente sette argomenti posizionali:

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

Oppure potremmo usare un argomento format string che sarà ripetuto come molti argomenti inviati ...

Si noti che il nostro a è ancora un array! Solo il primo elemento è cambiato!

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

Sotto bash, quando si accede a un nome di variabile senza specificare l'indice, si rivolge sempre solo al primo elemento!

Quindi, per recuperare il nostro array di sette campi, dobbiamo solo reimpostare il primo elemento:

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

Una stringa di formato di argomento con molti argomenti passati a:

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

Utilizzando la sintassi della domanda Stack overflow:

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

Nota: l'uso di double-quotes può essere utile per manipolare stringhe che contengono spaces, tabulations e/o newlines

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

Shell ora

Sotto POSIX Shell, non è possibile usare bashisms, quindi non esiste builtinprintf.

Fondamentalmente

Ma potresti semplicemente fare:

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

Formattato, usando forkedprintf

Se si desidera utilizzare costruzioni più sofisticate, è necessario utilizzare fork (nuovo processo figlio che esegue il lavoro e restituisce il risultato tramite stdout):

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

Storicamente, è possibile utilizzare backticks per recuperare il risultato di un fork:

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

Ma questo non è facile per nesting:

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

con i backtick, devi sfuggire alle forcelle interne con backslash:

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

Puoi farlo anche tu:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh
123
userend
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"

Uscirà

helloohaikthxbye

Ciò è utile quando $blaohai porta a un errore di variabile non trovata. O se hai spazi o altri caratteri speciali nelle tue corde. "${foo}" evita correttamente qualsiasi cosa tu inserisca.

115
orkoden
foo="Hello "
foo="$foo World"

41
vinothkr

Il modo in cui risolverei il problema è giusto

$a$b

Per esempio,

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

che produce

Hello World

Se si tenta di concatenare una stringa con un'altra stringa, ad esempio,

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

allora produrrà echo "$c"

Hello World

con uno spazio extra.

$aWorld

non funziona, come puoi immaginare, ma

${a}World

produce

HelloWorld
32
Chris Smith
$ a=hip
$ b=hop
$ ab=$a$b
$ echo $ab
hiphop
$ echo $a$b
hiphop
27
bcosca

Ecco un breve riassunto di ciò di cui la maggior parte delle risposte sta parlando.

Diciamo che abbiamo due variabili:

a=hello
b=world

La tabella seguente spiega i diversi contesti in cui possiamo combinare i valori di a e b per creare una nuova variabile, 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, 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

Alcune note:

  • racchiudere l'RHS di un incarico tra virgolette è generalmente una buona pratica, anche se in molti casi è abbastanza facoltativo
  • += è migliore dal punto di vista delle prestazioni se viene costruita una grande stringa in piccoli incrementi, specialmente in un ciclo
  • usa {} attorno ai nomi delle variabili per disambiguare la loro espansione (come nella riga 2 nella tabella sopra)

Guarda anche:

20
codeforester

Se vuoi aggiungere qualcosa come un trattino basso, usa escape (\)

FILEPATH=/opt/myfile

Questo fa not work:

echo $FILEPATH_$DATEX

Questo funziona bene:

echo $FILEPATH\\_$DATEX
20
user2800471

Ancora un altro approccio ...

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

... e ancora un altro.

> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
19
Akseli Palén

Il modo più semplice con le virgolette:

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

Puoi concatenare senza le virgolette. Ecco un esempio:

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

Quest'ultima affermazione stamperebbe "OpenSystems" (senza virgolette).

Questo è un esempio di uno script Bash:

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

Anche se l'operatore + = è ora consentito, è stato introdotto in Bash 3.1 nel 2004.

Qualsiasi script che usi questo operatore nelle versioni precedenti di Bash fallirà con un errore "comando non trovato" se sei fortunato, o un "errore di sintassi vicino a un token imprevisto".

Per coloro che si preoccupano della compatibilità con le versioni precedenti, segui i vecchi metodi di concatenazione Bash standard, come quelli menzionati nella risposta scelta:

foo="Hello"
foo="$foo World"
echo $foo
> Hello World
14
Louis-Félix

Preferisco usare le parentesi graffe ${} per la variabile espandibile nella stringa:

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

Le parentesi graffe si adattano all'utilizzo di stringhe continue:

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

Altrimenti usare foo = "$fooWorld" non funzionerà.

13
Nick Tsai

Modo più sicuro:

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

Le stringhe contenenti spazi possono diventare parte del comando, utilizzare "$ XXX" e "$ {XXX}" per evitare questi errori.

Inoltre dai un'occhiata ad altre risposte su + =

7
Bohdan

Se quello che stai cercando di fare è dividere una stringa in più righe, puoi usare una barra rovesciata:

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

Con uno spazio in mezzo:

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

Questo aggiunge anche solo uno spazio in mezzo:

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

C'è un caso particolare in cui dovresti fare attenzione:

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

Produrrà "daniel"san, e non danielsan, come potresti aver desiderato. In questo caso dovresti fare invece:

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

Se è il tuo esempio di aggiungere " World" alla stringa originale, allora può essere:

#!/bin/bash

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

L'output:

Hello World
5
var1='hello'
var2='world'
var3=$var1" "$var2 
echo $var3
5
hari

Ci sono preoccupazioni espresse sulle prestazioni, ma non vengono offerti dati. Lasciatemi suggerire un semplice test.

(NOTA: date su macOS non offre nanosecondi, quindi questo deve essere fatto su Linux.)

Ho creato append_test.sh su GitHub con i contenuti:

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

Gli errori indicano che il mio Bash è arrivato a 335.54432 MB prima che si arrestasse in modo anomalo. È possibile modificare il codice dal raddoppio dei dati all'aggiunta di una costante per ottenere un grafico più dettagliato e un punto di errore. Ma penso che questo dovrebbe darti abbastanza informazioni per decidere se ti interessa. Personalmente, sotto i 100 MB non lo faccio. Il tuo chilometraggio può variare.

4
Bruno Bronosky
a="Hello,"
a=$a" World!"
echo $a

Questo è il modo in cui si concatenano due stringhe.

4
CodeNinjaPI

Volevo costruire una stringa da una lista. Non ho trovato una risposta per questo, quindi la postò qui. Ecco cosa ho fatto:

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

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

echo ${string}

e poi ottengo il seguente risultato:

1 2 3 4 5
4
Simon Bachmann

Nota che questo non funzionerà

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

dato che sembra cadere $ pippo e ti lascia con:

PREFIX_WORLD

ma questo funzionerà:

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

e ti lascia con l'output corretto:

PREFIX_HELLO_WORLD

3
Dss

Lo faccio in questo modo quando conveniente: usa un comando in linea!

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

Ecco quello attraverso AWK :

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