variable unir literal concatenate concatenar cadenas and bash shell syntax append string-concatenation

unir - Cómo concatenar variables de cadena en Bash



unir cadenas en bash (28)

Bash primero

Como esta pregunta representa específicamente a Bash , mi primera parte de la respuesta presentaría diferentes formas de hacerlo correctamente:

+= : Añadir a la variable

La sintaxis += se puede utilizar de diferentes maneras:

Añadir a la cadena var+=...

(Debido a que soy frugal, solo usaré dos variables foo y a y luego reutilizaré lo mismo en toda la respuesta ;-)

a=2 a+=4 echo $a 24

Usando la sintaxis de pregunta de desbordamiento de pila ,

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

¡funciona bien!

Anexar a un entero ((var+=...))

la variable a es una cadena, pero también un entero

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

Anexar a una matriz var+=(...)

Nuestro a es también una matriz de un solo elemento.

echo ${a[@]} 36 a+=(18) echo ${a[@]} 36 18 echo ${a[0]} 36 echo ${a[1]} 18

Tenga en cuenta que entre paréntesis, hay una matriz separada por espacios . Si desea almacenar una cadena que contiene espacios en su matriz, tiene que incluirlos:

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

Hmm ... esto no es un error, sino una característica ... ¡Para evitar que bash intente desarrollar !" , Podrías:

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 : reconstruir la variable usando el comando incorporado

El comando incorporado printf proporciona una forma poderosa de dibujar formato de cadena. Como este es un Bash incorporado , hay una opción para enviar una cadena con formato a una variable en lugar de imprimir en la stdout :

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

Hay siete cadenas en esta matriz. Entonces podríamos construir una cadena formateada que contenga exactamente siete argumentos posicionales:

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

O podríamos usar una cadena de formato de argumento que se repetirá a medida que muchos argumentos se presenten ...

Tenga en cuenta que nuestro a es todavía una matriz! ¡Solo se cambia el primer elemento!

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

Bajo bash, cuando accede a un nombre de variable sin especificar el índice, ¡siempre direcciona solo el primer elemento!

Así que para recuperar nuestra matriz de siete campos, solo necesitamos restablecer el primer 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 cadena de formato de argumento con muchos argumentos pasados ​​a:

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

Usando la sintaxis de la pregunta de desbordamiento de pila :

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

Nota: El uso de comillas dobles puede ser útil para manipular cadenas que contienen spaces , tabulations y / o newlines

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

Shell ahora

Bajo el shell POSIX , no se podían usar bashismos , por lo que no hay printf incorporado .

Básicamente

Pero simplemente podrías hacer:

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

Formato, utilizando printf bifurcado.

Si desea usar construcciones más sofisticadas, tiene que usar una bifurcación (nuevo proceso secundario que hace el trabajo y devuelve el resultado a través de la stdout ):

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

Históricamente, podría usar backticks para recuperar el resultado de una bifurcación :

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

Pero esto no es fácil para anidar :

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

con backticks, tienes que escapar de las horquillas internas con barras invertidas :

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

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

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

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

¿Cómo se logra esto en Bash?


Aquí está el uno a través de AWK :

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


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 donde 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:

  • En general, encerrar el RHS de una tarea entre comillas dobles es una buena práctica, aunque en muchos casos es bastante opcional
  • += es mejor desde el punto de vista del rendimiento si una cadena grande se está construyendo en pequeños incrementos, especialmente en un bucle
  • use {} alrededor de los nombres de las variables para desambiguar su expansión (como en la fila 2 de la tabla anterior)

Ver también:


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

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


Hay un caso particular en el que debes tener cuidado:

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

danielsan "daniel"san , y no danielsan , como podrías haber deseado. En este caso deberías hacer en su lugar:

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


Incluso si ahora se permite el operador + =, se ha introducido en Bash 3.1 en 2004.

Cualquier script que use este operador en 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, siga los métodos de concatenación Bash estándar más antiguos, como los mencionados en la respuesta elegida:

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


La forma en que solucionaría el problema es simplemente

$a$b

Por ejemplo,

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

que produce

Hello World

Si intenta concatenar una cadena con otra cadena, por ejemplo,

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

entonces echo "$c" producirá

Hello World

Con un espacio extra.

$aWorld

no funciona, como puedes imaginar, pero

${a}World

produce

HelloWorld


La forma más sencilla con comillas:

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


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`"


Manera más segura:

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

Las cadenas que contienen espacios pueden convertirse en parte del comando, use "$ XXX" y "$ {XXX}" para evitar estos errores.

Además, echa un vistazo a otra respuesta sobre + =


Me gusta hacer una función rápida.

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

Otra forma de pelar a un gato. Esta vez con funciones: D


Prefiero usar rizos ${} para expandir la variable en la cadena:

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

Los corchetes se ajustarán al uso continuo de la cadena:

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

De lo contrario, usar foo = "$fooWorld" no funcionará.


Puedes concatenar sin las comillas. Aquí hay un ejemplo:

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

Esta última declaración imprimiría "OpenSystems" (sin comillas).

Este es un ejemplo de un script Bash:

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


Puedes probar el siguiente camino. Cuando tiene lugar la sustitución, las comillas dobles mantendrán los espacios.

var1="Ram " var2="Lakshmana" echo $var1$var2 or echo var1+=$var2 "bash support += operation. bcsmc2rtese001 [/tmp]$ var1="Ram " bcsmc2rtese001 [/tmp]$ var2="Lakshmana" bcsmc2rtese001 [/tmp]$ echo $var1$var2 Ram Lakshmana bcsmc2rtese001 [/tmp]$ var1+=$var2 bcsmc2rtese001 [/tmp]$ echo $var1 Ram Lakshmana


Quería construir una cadena de una lista. No pude encontrar una respuesta para eso, así que la publico aquí. Aquí esta lo que hice:

list=(1 2 3 4 5) string='''' for elm in "${list[@]}"; do string="${string} ${elm}" done echo ${string}

y luego me sale el siguiente resultado:

1 2 3 4 5


Se expresan preocupaciones sobre el rendimiento, pero no se ofrecen datos. Déjame sugerir 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 el contenido:

#!/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 llegó a 335.54432 MB antes de que se estrellara. Podría cambiar el código de duplicar los datos a agregar una constante para obtener un gráfico más detallado y un punto de falla. Pero creo que esto debería darte suficiente información para decidir si te importa. Personalmente, por debajo de 100 MB no lo hago. 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


Si es como tu 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 intentas hacer es dividir una cadena en varias líneas, puedes usar una barra invertida:

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

Con un espacio en el medio:

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

Este también agrega solo un espacio en medio:

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


Sin embargo, otro enfoque ...

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

... y aún otro más.

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


También puedes hacer esto:

$ var="myscript" $ echo $var myscript $ var=${var}.sh $ echo $var myscript.sh


Tenga en cuenta que esto no funcionará

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

Como parece caer $ foo y te deja con:

PREFIX_WORLD

pero esto funcionará:

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

y te dejo con la salida correcta:

PREFIX_HELLO_WORLD


Todavía no sé sobre PHP, pero esto funciona en Linux Bash. Si no quieres afectarlo a una variable, puedes intentar esto:

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

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


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


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

Saldrá

helloohaikthxbye

Esto es útil cuando $blaohai conduce a un error de variable no encontrada. O si tiene espacios u otros caracteres especiales en sus cadenas. "${foo}" escapa adecuadamente a todo lo que le pongas.


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


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

En general, para concatenar dos variables, puede escribirlas una tras otra:

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


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