No PHP, as seqüências de caracteres são concatenadas da seguinte maneira:
$foo = "Hello";
$foo .= " World";
Aqui, $foo
torna-se "Olá Mundo".
Como isso é feito no Bash?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
No PHP, as seqüências de caracteres são concatenadas da seguinte maneira:
$foo = "Hello";
$foo .= " World";
Aqui, $foo
torna-se "Olá Mundo".
Como isso é feito no Bash?
foo1="World" foo2="Hello" foo3="$foo1$foo2"
Respostas:
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
Em geral, para concatenar duas variáveis, basta escrevê-las uma após a outra:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
$foo
aspas duplas, nos momentos em que realmente importa.
foo="$fooworld"
? Eu diria que não ...
fooworld
. Disambiguating que é feito com colchetes, como foo="${foo}world"
...
O Bash também suporta um +=
operador, como mostrado neste código:
$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
export A+="Z"
ou talvez a A
variável precise ser exportada apenas uma vez?
export A+=Z
funcionam muito bem.
#!/bin/sh
um script usando essa construção.
bash
e em alguns outros shells mais avançados. Não funcionará sob busybox sh
ou dash
(que está /bin/sh
em muitas distros), ou em alguns outros shells, como o /bin/sh
fornecido no FreeBSD.
Como esta pergunta se refere especificamente ao Bash , minha primeira parte da resposta apresentaria diferentes maneiras de fazer isso corretamente:
+=
: Anexar à variávelA sintaxe +=
pode ser usada de diferentes maneiras:
var+=...
(Porque eu sou frugal, eu só vai usar duas variáveis foo
e a
em seguida, re-utilizar o mesmo em toda a resposta. ;-)
a=2
a+=4
echo $a
24
Usando a sintaxe da pergunta Stack Overflow ,
foo="Hello"
foo+=" World"
echo $foo
Hello World
funciona bem!
((var+=...))
A variável a
é uma sequência, mas também um número inteiro
echo $a
24
((a+=12))
echo $a
36
var+=(...)
Nossa 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 sequência contendo espaços em sua matriz, é necessário incluí-los:
a+=(one word "hello world!" )
bash: !": event not found
Hmm .. isso não é um bug, mas um recurso ... Para impedir que o bash tente se desenvolver !"
, você pode:
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
: Reconstrua a variável usando o comando embutidoO comando printf
interno fornece uma maneira poderosa de desenhar o formato de sequência. Como este é um Bash embutido , há 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 strings nessa matriz. Assim, 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!")'
No bash, quando você acessa um nome de variável sem especificar o índice, sempre aborda apenas o primeiro elemento!
Portanto, para recuperar nossa matriz de sete campos, precisamos redefinir apenas o 1º 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 sequência de formato de argumento com muitos argumentos transmitidos para:
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
Nota: O uso de aspas podem ser úteis para a manipulação de cadeias que contêm spaces
, tabulations
e / ounewlines
printf -v foo "%s World" "$foo"
Sob o shell POSIX , você não pode usar basismos , portanto, não há construtores printf
.
Mas você poderia simplesmente fazer:
foo="Hello"
foo="$foo World"
echo $foo
Hello World
printf
Se você quiser usar construções mais sofisticadas, precisará usar um fork (novo processo filho que faz o trabalho e retorna o resultado via stdout
):
foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World
Historicamente, você poderia usar reticulares para recuperar o resultado de um garfo :
foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World
Mas isso não é fácil para aninhar :
foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013
com barras, você precisa escapar dos 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
+=
operador também é muito mais rápido do que $a="$a$b"
nos meus testes. O que faz sentido.
var=${var}.sh
exemplo de outras respostas, o que é muito útil.
bash
o único shell com +=
operador? Quero ver se ele é portátil o suficiente
+=
operador, mas todas essas formas são basismos , portanto não portáteis! Mesmo você pode encontrar um bug especial em caso de versão errada do bash!
Você também pode fazer isso:
$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh
var=myscript;var=$var.sh;echo $var
teriam os mesmos efeitos (este trabalho em bash, dash, busybox e outros).
echo $var2
não produzmyscript2
.
ilegal no nome da variável. Se outra pessoa echo ${var}2
ou ver a minha resposta
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"
Saída
helloohaikthxbye
Isso é útil quando
$blaohai
leva a um erro de variável não encontrada. Ou se você tiver espaços ou outros caracteres especiais em suas seqüências. "${foo}"
escapa adequadamente tudo o que você coloca nele.
foo="Hello "
foo="$foo World"
A maneira como eu resolveria o problema é apenas
$a$b
Por exemplo,
a="Hello"
b=" World"
c=$a$b
echo "$c"
que produz
Hello World
Se você tentar concatenar uma sequência com outra, por exemplo,
a="Hello"
c="$a World"
então echo "$c"
irá produzir
Hello World
com um espaço extra.
$aWorld
não funciona, como você pode imaginar, mas
${a}World
produz
HelloWorld
${a}\ World
produzHello World
c=$a$b
aqui fazer a mesma coisa que c=$a World
(que tentaria executar World
como um comando). Eu acho que significa que a atribuição é analisado antes de as variáveis são expandidas ..
Aqui está um resumo conciso do que a maioria das respostas está falando.
Digamos que temos duas variáveis e $ 1 é definido como 'one':
set one two
a=hello
b=world
A tabela abaixo explica os diferentes contextos em que podemos combinar os valores a
e b
criar uma nova variável 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
Algumas notas:
+=
é melhor do ponto de vista de desempenho se uma grande string estiver sendo construída em pequenos incrementos, especialmente em um loop{}
torno de nomes de variáveis para desambiguar sua expansão (como na linha 2 da tabela acima). Como visto nas linhas 3 e 4, não há necessidade, a {}
menos que uma variável esteja sendo concatenada com uma sequência que comece com um caractere que seja um primeiro caractere válido no nome da variável do shell, que é alfabeto ou sublinhado.Veja também:
Ainda outra abordagem ...
> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.
... e ainda mais um.
> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
Se você deseja acrescentar algo como um sublinhado, use escape (\)
FILEPATH=/opt/myfile
Isso não funciona:
echo $FILEPATH_$DATEX
Isso funciona bem:
echo $FILEPATH\\_$DATEX
echo $a\_$b
faria. Como sugerido no comentário de Nik O'Lai, o sublinhado é um personagem regular. O manuseio de espaços em branco é muito mais sensível a seqüências de caracteres, eco e concatenação - é possível usar \
e ler completamente este encadeamento, pois esse problema volta agora e depois.
A maneira mais simples com aspas:
B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
var=$B$b"a"; echo Hello\ $var
faria, acredito eu #
Você pode concatenar sem as aspas. Aqui está um exemplo:
$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3
Esta última declaração imprimiria "OpenSystems" (sem aspas).
Este é um exemplo de script Bash:
v1=hello
v2=world
v3="$v1 $v2"
echo $v3 # Output: hello world
echo "$v3" # Output: hello world
Mesmo que o operador + = agora seja permitido, ele foi introduzido no Bash 3.1 em 2004.
Qualquer script que use esse operador em versões mais antigas do Bash falhará com um erro "comando não encontrado" se você tiver sorte ou com um "erro de sintaxe próximo ao token inesperado".
Para quem se preocupa com a compatibilidade com versões anteriores, siga os métodos de concatenação Bash padrão mais antigos, como os mencionados na resposta escolhida:
foo="Hello"
foo="$foo World"
echo $foo
> Hello World
Se o que você está tentando fazer é dividir uma sequência em várias linhas, você pode usar uma barra invertida:
$ a="hello\
> world"
$ echo $a
helloworld
Com um espaço no meio:
$ a="hello \
> world"
$ echo $a
hello world
Este também adiciona apenas um espaço no meio:
$ a="hello \
> world"
$ echo $a
hello world
Maneira mais segura:
a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD
Seqüências de caracteres que contêm espaços podem se tornar parte do comando, use "$ XXX" e "$ {XXX}" para evitar esses erros.
Além disso, dê uma olhada em outras respostas sobre + =
d=DD DD
, daria DD: command not found
--- note que esse é o último DD, e não o que foi encontrado. Se todos os operandos estiverem formatados corretamente e já contiverem os espaços necessários, você poderá simplesmente concatenar com s=${a}${b}${c}${d}; echo $s
, com menos aspas. Além disso, você pode usar \
(espaço em branco com escape) para evitar esses problemas - d=echo\ echo
não iniciará nenhuma chamada de eco, enquanto o d=echo echo
fará.
a="Hello,"
a=$a" World!"
echo $a
É assim que você concatena duas strings.
Se for o seu exemplo de adição " World"
à string original, poderá ser:
#!/bin/bash
foo="Hello"
foo=$foo" World"
echo $foo
A saída:
Hello World
var1='hello'
var2='world'
var3=$var1" "$var2
echo $var3
var3=$var1\ $var2
tem o mesmo efeito
Há preocupações expressas sobre desempenho, mas nenhum dado é oferecido. Deixe-me sugerir um teste simples.
(NOTA: date
no macOS não oferece nanossegundos, portanto, 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 chegou a 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 fornecer informações suficientes para decidir se você se importa. Pessoalmente, abaixo de 100 MB, não. Sua milhagem pode variar.
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"
(Tente isso em um host não produtivo !!;)
Eu queria construir uma string a partir de uma lista. Não foi possível encontrar uma resposta para isso, então eu posto aqui. Aqui está o que eu fiz:
list=(1 2 3 4 5)
string=''
for elm in "${list[@]}"; do
string="${string} ${elm}"
done
echo ${string}
e então recebo a seguinte saída:
1 2 3 4 5
Observe que isso não vai funcionar
foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar
como parece soltar $ 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
Faço-o desta maneira quando conveniente: Use um comando embutido!
echo "The current time is `date`"
echo "Current User: `echo $USER`"
date "+The current time is %a %b %d %Y +%T"
vez de echo ...$(date)
. Sob recente bash, você poderia escrever: printf "The current time is %(%a %b %d %Y +%T)T\n" -1
.
Na minha opinião, a maneira mais simples de concatenar duas strings é escrever uma função que faça isso por você e, em seguida, usar essa função.
function concat ()
{
prefix=$1
suffix=$2
echo "${prefix}${suffix}"
}
foo="Super"
bar="man"
concat $foo $bar # Superman
alien=$(concat $foo $bar)
echo $alien # Superman
Eu meio que gosto de fazer uma função rápida.
#! /bin/sh -f
function combo() {
echo $@
}
echo $(combo 'foo''bar')
Mais uma maneira de esfolar um gato. Desta vez com funções: D
Ainda não sei o PHP, mas isso funciona no Linux Bash. Se você não deseja afetá-lo em uma variável, tente o seguinte:
read pp; *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;
>Hello World!
Você pode colocar outra variável em vez de 'Hello' ou '!'. Você também pode concatenar mais seqüências de caracteres.
foo="Hello"
foo=$foo" World"
echo $foo
esta vez trabalhou para "#! / bin / sh!"