script - variables on bash




Como concatenar variáveis de string no Bash (19)

Bash primeiro

Como essa questão é especificamente para Bash , minha primeira parte da resposta apresentaria maneiras diferentes de fazer isso corretamente:

+= : Anexar à variável

A sintaxe += pode ser usada de diferentes maneiras:

Anexar à string var+=...

(Porque eu sou frugal, vou usar apenas duas variáveis foo e foo depois reutilizá-las em toda a resposta. ;-)

a=2
a+=4
echo $a
24

Usando a sintaxe de pergunta do Stack Overflow ,

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

funciona bem!

Anexar a um inteiro ((var+=...))

variável a é uma string, mas também um inteiro

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

Acrescente a um array var+=(...)

Nosso a é também uma matriz de apenas um elemento.

echo ${a[@]}
36

a+=(18)

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

Observe que, entre parênteses, há uma matriz separada por espaço . Se você deseja armazenar uma string contendo espaços em sua matriz, você deve colocá-los:

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

Hmm .. isso não é um bug, mas um recurso ... Para evitar que o bash tente se desenvolver !" , Você poderia:

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 : Re-construct variable usando o comando incorporado

O comando printf builtin oferece uma maneira poderosa de desenhar o formato de string. Como este é um Bash interno , existe uma opção para enviar uma string formatada para uma variável em vez de imprimir em stdout :

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

Existem sete cadeias nesta matriz. Então, poderíamos construir uma string formatada contendo exatamente sete argumentos posicionais:

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

Ou podemos usar uma string de formato de argumento que será repetida como muitos argumentos enviados ...

Note que o nosso a ainda é um array! Apenas o primeiro elemento é alterado!

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

Sob bash, quando você acessa um nome de variável sem especificar o índice, você sempre endereça somente o primeiro elemento!

Então, para recuperar nosso array de sete campos, precisamos apenas re-definir o primeiro 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!")'

Uma string de formato de argumento com muitos argumentos passados ​​para:

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

Usando a sintaxe de pergunta do Stack Overflow :

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

Nota: O uso de aspas duplas pode ser útil para manipular strings que contenham spaces , tabulations e / ou newlines

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

Shell agora

Sob o shell POSIX , você não pode usar bashisms , então não há printf embutido .

Basicamente

Mas você poderia simplesmente fazer:

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

Formatado, usando printf bifurcado

Se você quiser usar construções mais sofisticadas, use um fork (novo processo filho que faz o job e retorna o resultado via stdout ):

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

Historicamente, você poderia usar backticks para recuperar o resultado de um fork :

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

Mas isso não é fácil para aninhamento :

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

com backticks, você tem que escapar de garfos internos com barras invertidas :

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

No PHP, as strings são concatenadas juntas da seguinte maneira:

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

Aqui, $foo se torna "Hello World".

Como isso é feito em Bash?


A maneira mais simples com aspas:

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

Ainda outra abordagem ...

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

... e ainda outro.

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

Aqui está o do AWK :

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

Caminho mais seguro:

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

Strings contendo espaços podem se tornar parte do comando, use "$ XXX" e "$ {XXX}" para evitar esses erros.

Além disso, dê uma olhada em outra resposta sobre + =


Eu faço desta forma quando conveniente: use um comando inline!

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

Eu não sei sobre PHP ainda, mas isso funciona no Linux Bash. Se você não quiser afetá-lo para uma variável, você pode tentar isto:

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

>Hello World!

Você poderia colocar outra variável em vez de 'Hello' ou '!'. Você pode concatenar mais strings também.


Eu prefiro usar chaves ${} para expandir a variável na string:

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

Os colchetes encaracolados se encaixam no uso contínuo de cordas:

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

Caso contrário, usar foo = "$fooWorld" não funcionará.


Existe um caso particular em que você deve tomar cuidado:

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

Vai produzir "daniel"san , e não danielsan , como você poderia querer. Nesse caso, você deve fazer em vez disso:

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

Há dúvidas sobre o desempenho, mas nenhum dado é oferecido. Deixe-me sugerir um teste simples.

(NOTA: a date no macOS não oferece nanossegundos, então isso deve ser feito no Linux.)

Eu criei append_test.sh no GitHub com o conteúdo:

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

Teste 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

Teste 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

Os erros indicam que meu Bash subiu para 335.54432 MB antes de travar . Você pode alterar o código de duplicar os dados para acrescentar uma constante para obter um gráfico mais granular e um ponto de falha. Mas acho que isso deve lhe dar informações suficientes para decidir se você se importa. Pessoalmente, abaixo de 100 MB eu não faço. Sua milhagem pode variar.


Note que isso não vai funcionar

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

como parece cair $ foo e deixa você com:

PREFIX_WORLD

mas isso vai funcionar:

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

e deixar você com a saída correta:

PREFIX_HELLO_WORLD


O Bash também suporta um operador + =, conforme mostrado na seguinte transcrição:

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

Se o que você está tentando fazer é dividir uma string em várias linhas, você pode usar uma barra invertida:

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

Com um espaço entre eles:

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

Este também adiciona apenas um espaço entre eles:

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

Se você quiser acrescentar algo como um sublinhado, use escape (\)

FILEPATH=/opt/myfile

Isso não funciona:

echo $FILEPATH_$DATEX

Isso funciona bem:

echo $FILEPATH\\_$DATEX

Você pode tentar o caminho abaixo. Quando a substituição ocorre, as aspas duplas mantêm os espaços.

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

Você também pode fazer isso:

$ var="myscript"

$ echo $var

myscript


$ var=${var}.sh

$ echo $var

myscript.sh

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

Saída

helloohaikthxbye

Isso é útil quando $blaohai leva a uma variável não encontrada erro. Ou se você tiver espaços ou outros caracteres especiais nas suas strings. "${foo}" apropriadamente escapa de qualquer coisa que você coloca nele.


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


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






string-concatenation