Cómo concatenar variables de cadena en Bash


12 Answers

Bash también admite un operador + = como se muestra en la siguiente transcripción:

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

En PHP, las cadenas se concatenan juntas de la siguiente manera:

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

Aquí, $foo convierte en "Hello World".

¿Cómo se logra esto en Bash?




Todavía no sé nada de PHP, pero esto funciona en Linux Bash. Si no desea afectarlo a una variable, puede intentar esto:

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

>Hello World!

Puede colocar otra variable en lugar de 'Hola' o '!'. También podría concatenar más cadenas.




Si es como su ejemplo de agregar " World" a la cadena original, entonces puede ser:

#!/bin/bash

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

La salida:

Hello World



Si lo que intenta hacer es dividir una cadena en varias líneas, puede usar una barra diagonal inversa:

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

Con un espacio intermedio:

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

Este también agrega solo un espacio en el medio:

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



Usted puede hacer esto también:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh



Aquí hay un resumen conciso de lo que la mayoría de las respuestas están hablando.

Digamos que tenemos dos variables:

a=hello
b=world

La siguiente tabla explica los diferentes contextos en los que podemos combinar los valores de a y b para crear una nueva variable, 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

Algunas notas:

  • adjuntar el RHS de una tarea entre comillas dobles es generalmente una buena práctica, aunque es bastante opcional en muchos casos
  • += es mejor desde el punto de vista del rendimiento si se está construyendo una gran cadena en pequeños incrementos, especialmente en un ciclo
  • use {} alrededor de nombres de variables para eliminar la ambigüedad de su expansión (como en la fila 2 en la tabla anterior)

Ver también:




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



Hay un caso particular en el que debes tener cuidado:

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

danielsan salida a "daniel"san , y no a danielsan , como hubieras querido. En este caso, debe hacer en su lugar:

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



Hay inquietudes expresadas sobre el rendimiento, pero no se ofrecen datos. Déjame sugerirte una prueba simple.

(NOTA: la date en macOS no ofrece nanosegundos, por lo que esto debe hacerse en Linux.)

He creado append_test.sh en GitHub con los contenidos:

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

Prueba 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

Prueba 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

Los errores indican que mi Bash obtuvo hasta 335.54432 MB antes de que se bloquee . Podría cambiar el código de duplicar los datos a agregar una constante para obtener un gráfico más granular y un punto de falla. Pero creo que esto debería darte suficiente información para decidir si te importa. Personalmente, debajo de 100 MB, no. Su experiencia puede ser diferente.




Si desea agregar algo como un guión bajo, use escape (\)

FILEPATH=/opt/myfile

Esto no funciona:

echo $FILEPATH_$DATEX

Esto funciona bien:

echo $FILEPATH\\_$DATEX



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




Lo hago de esta manera cuando sea conveniente: ¡use un comando en línea!

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



Incluso si el operador + = ahora está permitido, se introdujo en Bash 3.1 en 2004.

Cualquier secuencia de comandos que use este operador en las versiones anteriores de Bash fallará con un error de "comando no encontrado" si tiene suerte, o un "error de sintaxis cerca del token inesperado".

Para aquellos que se preocupan por la compatibilidad con versiones anteriores, se adhieren a los métodos estándar de concatenación de Bash, como los mencionados en la respuesta elegida:

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



Related