Ответы:
foo="Hello"
foo="${foo} World"
echo "${foo}"
> Hello World
В общем, для объединения двух переменных вы можете просто записать их одну за другой:
a='Hello'
b='World'
c="${a} ${b}"
echo "${c}"
> Hello World
$fooдвойные кавычки, для тех случаев, когда это действительно имеет значение.
foo="$fooworld"? Я бы предположил, что нет ...
fooworld. foo="${foo}world"
Bash также поддерживает +=оператор, как показано в этом коде:
$ A="X Y"
$ A+=" Z"
$ echo "$A"
X Y Z
export A+="Z"или, может быть, Aпеременную нужно экспортировать только один раз?
export A+=Zэто тоже очень хорошо работает.
#!/bin/shв сценарии, использующем эту конструкцию.
bashнекоторых и более продвинутых оболочках. Он не будет работать busybox shни с dash( или (что /bin/shна многих дистрибутивах)), ни с некоторыми другими оболочками, такими как /bin/shпредоставленные во FreeBSD.
Поскольку этот вопрос предназначен специально для Bash , моя первая часть ответа представит различные способы сделать это правильно:
+=: Добавить к переменнойСинтаксис +=может использоваться по-разному:
var+=...(Потому что я скромный, я буду использовать только две переменные fooи aзатем повторно использовать то же самое в целом ответ ;-).
a=2
a+=4
echo $a
24
Используя синтаксис вопроса Stack Overflow ,
foo="Hello"
foo+=" World"
echo $foo
Hello World
работает отлично!
((var+=...))переменная a- это строка, но также целое число
echo $a
24
((a+=12))
echo $a
36
var+=(...)Наш aмассив также состоит только из одного элемента.
echo ${a[@]}
36
a+=(18)
echo ${a[@]}
36 18
echo ${a[0]}
36
echo ${a[1]}
18
Обратите внимание, что между скобками находится разделенный пробелами массив . Если вы хотите сохранить строку, содержащую пробелы в вашем массиве, вы должны заключить их:
a+=(one word "hello world!" )
bash: !": event not found
Хм .. это не ошибка, а особенность ... Чтобы предотвратить попытки разработки bash !", вы можете:
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: Перестроить переменную с помощью встроенной командыprintf Встроенная команда дает мощный способ рисования формат строки. Поскольку это встроенная функция Bash , существует возможность отправки отформатированной строки в переменную вместо печати на stdout:
echo ${a[@]}
36 18 one word hello world! hello world! hello world!
В этом массиве семь строк . Таким образом, мы можем построить отформатированную строку, содержащую ровно семь позиционных аргументов:
printf -v a "%s./.%s...'%s' '%s', '%s'=='%s'=='%s'" "${a[@]}"
echo $a
36./.18...'one' 'word', 'hello world!'=='hello world!'=='hello world!'
Или мы могли бы использовать одну строку формата аргумента, которая будет повторяться столько же аргументов, сколько представлено ...
Обратите внимание, что наше aвсе еще массив! Только первый элемент изменен!
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!")'
В bash, когда вы обращаетесь к имени переменной без указания индекса, вы всегда обращаетесь только к первому элементу!
Таким образом, чтобы получить наш массив из семи полей, нам нужно только переустановить 1-й элемент:
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!")'
Строка формата с одним аргументом и многими аргументами:
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: Использование двойных кавычек может быть полезно для работы со строками , которые содержат spaces, tabulationsи / илиnewlines
printf -v foo "%s World" "$foo"
В оболочке POSIX вы не можете использовать bashisms , поэтому нет встроенных printf .
Но вы могли бы просто сделать:
foo="Hello"
foo="$foo World"
echo $foo
Hello World
printfЕсли вы хотите использовать более сложные конструкции, вы должны использовать форк (новый дочерний процесс, который выполняет задание и возвращает результат через stdout):
foo="Hello"
foo=$(printf "%s World" "$foo")
echo $foo
Hello World
Исторически, вы могли использовать обратные пометки для получения результата форка :
foo="Hello"
foo=`printf "%s World" "$foo"`
echo $foo
Hello World
Но это не легко для вложения :
foo="Today is: "
foo=$(printf "%s %s" "$foo" "$(date)")
echo $foo
Today is: Sun Aug 4 11:58:23 CEST 2013
с обратными чертами вы должны избегать внутренних вилок с обратными слешами :
foo="Today is: "
foo=`printf "%s %s" "$foo" "\`date\`"`
echo $foo
Today is: Sun Aug 4 11:59:10 CEST 2013
+=Оператор также намного быстрее , чем $a="$a$b"в моих тестах .. Какой смысл.
var=${var}.shпример из других ответов, что очень полезно.
bashединственная оболочка с +=оператором? Я хочу посмотреть, достаточно ли она портативна
+=оператором, но все эти способы - башмы , поэтому не переносимы! Даже вы можете столкнуться со специальной ошибкой в случае неправильной версии bash!
Ты тоже можешь это сделать:
$ var="myscript"
$ echo $var
myscript
$ var=${var}.sh
$ echo $var
myscript.sh
var=myscript;var=$var.sh;echo $varбудут иметь те же эффекты (это работает в bash, dash, busybox и других).
echo $var2, не производитmyscript2
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"
Будет выходной
helloohaikthxbye
Это полезно, когда
$blaohai
приводит к ошибке переменной not found. Или если у вас есть пробелы или другие специальные символы в ваших строках. "${foo}"правильно избегает всего, что вы положили в него.
foo="Hello "
foo="$foo World"
Я бы решил проблему просто
$a$b
Например,
a="Hello"
b=" World"
c=$a$b
echo "$c"
который производит
Hello World
Если вы попытаетесь объединить строку с другой строкой, например,
a="Hello"
c="$a World"
потом echo "$c"будет производить
Hello World
с дополнительным пространством.
$aWorld
не работает, как вы можете себе представить, но
${a}World
производит
HelloWorld
${a}\ WorldпроизводитHello World
c=$a$bздесь сделать то же самое, что c=$a World(который будет пытаться запускаться Worldкак команда). Я предполагаю, что это означает, что присвоение анализируется до
Вот краткое резюме того, о чем говорит большинство ответов.
Допустим, у нас есть две переменные и $ 1 установлен на «один»:
set one two
a=hello
b=world
Таблица ниже объясняет различные контексты, в которых мы можем комбинировать значения aи bсоздавать новую переменную 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
Несколько заметок:
+= лучше с точки зрения производительности, если большая строка строится с небольшими приращениями, особенно в цикле{}вокруг имен переменных, чтобы устранить неоднозначность их расширения (как в строке 2 в таблице выше). Как видно из строк 3 и 4, в этом нет необходимости, {}если переменная не конкатенируется со строкой, которая начинается с символа, который является допустимым первым символом в имени переменной оболочки, то есть является алфавитом или подчеркиванием.Смотрите также:
Еще один подход ...
> H="Hello "
> U="$H""universe."
> echo $U
Hello universe.
... и еще один.
> H="Hello "
> U=$H"universe."
> echo $U
Hello universe.
Если вы хотите добавить что-то вроде подчеркивания, используйте escape (\)
FILEPATH=/opt/myfile
Это не работает:
echo $FILEPATH_$DATEX
Это прекрасно работает:
echo $FILEPATH\\_$DATEX
echo $a\_$bбудет. Как намекает в комментарии Ник О'Лай, подчеркивание является регулярным символом. Обработка пробелов намного более чувствительна к строкам, эхо и конкатенации - \ этот поток можно использовать и внимательно читать, так как эта проблема возникает время от времени.
Самый простой способ с кавычками:
B=Bar
b=bar
var="$B""$b""a"
echo "Hello ""$var"
var=$B$b"a"; echo Hello\ $varсделал бы, я верю
Вы можете объединить без кавычек. Вот пример:
$Variable1 Open
$Variable2 Systems
$Variable3 $Variable1$Variable2
$echo $Variable3
Это последнее утверждение напечатало бы "OpenSystems" (без кавычек).
Это пример скрипта Bash:
v1=hello
v2=world
v3="$v1 $v2"
echo $v3 # Output: hello world
echo "$v3" # Output: hello world
Даже если теперь разрешен оператор + =, он был введен в Bash 3.1 в 2004 году.
Любой сценарий, использующий этот оператор в старых версиях Bash, завершится с ошибкой «команда не найдена», если вам повезет, или с «синтаксической ошибкой рядом с неожиданным токеном».
Для тех, кому небезразлична обратная совместимость, придерживайтесь старых стандартных методов конкатенации Bash, таких как упомянутые в выбранном ответе:
foo="Hello"
foo="$foo World"
echo $foo
> Hello World
Я предпочитаю использовать фигурные скобки ${}для расширения переменной в строке:
foo="Hello"
foo="${foo} World"
echo $foo
> Hello World
Вьющиеся скобки подойдут для непрерывного использования строки:
foo="Hello"
foo="${foo}World"
echo $foo
> HelloWorld
В противном случае использование foo = "$fooWorld"не будет работать.
Если вы пытаетесь разделить строку на несколько строк, вы можете использовать обратную косую черту:
$ a="hello\
> world"
$ echo $a
helloworld
С одним пробелом между:
$ a="hello \
> world"
$ echo $a
hello world
Этот также добавляет только один пробел между:
$ a="hello \
> world"
$ echo $a
hello world
Более безопасный способ:
a="AAAAAAAAAAAA"
b="BBBBBBBBBBBB"
c="CCCCCCCCCCCC"
d="DD DD"
s="${a}${b}${c}${d}"
echo "$s"
AAAAAAAAAAAABBBBBBBBBBBBCCCCCCCCCCCCDD DD
Строки, содержащие пробелы, могут стать частью команды, используйте «$ XXX» и «$ {XXX}», чтобы избежать этих ошибок.
Плюс взгляните на другой ответ о + =
d=DD DDчто дайте DD: command not found--- обратите внимание, что это последний DD, а скорее d, который не найден. Если все операнды правильно отформатированы и уже содержат необходимые пробелы, вы можете просто объединить их s=${a}${b}${c}${d}; echo $sс меньшим количеством кавычек. Также вы можете использовать \ (экранированный пробел), чтобы избежать этих проблем - d=echo\ echoне будет запускать эхо-вызов, тогда как d=echo echoбудет.
Есть один конкретный случай, когда вы должны позаботиться:
user=daniel
cat > output.file << EOF
"$user"san
EOF
Будет выводить "daniel"san, а не так danielsan, как вы, возможно, хотели. В этом случае вы должны сделать вместо этого:
user=daniel
cat > output.file << EOF
${user}san
EOF
a="Hello,"
a=$a" World!"
echo $a
Вот как вы объединяете две строки.
Если это как ваш пример добавления " World"к исходной строке, то это может быть:
#!/bin/bash
foo="Hello"
foo=$foo" World"
echo $foo
Выход:
Hello World
var1='hello'
var2='world'
var3=$var1" "$var2
echo $var3
var3=$var1\ $var2имеет тот же эффект
Есть высказанные опасения по поводу производительности, но данные не предлагаются. Позвольте мне предложить простой тест.
(ПРИМЕЧАНИЕ: dateна macOS не предлагает наносекунд, поэтому это должно быть сделано на Linux.)
Я создал append_test.sh на GitHub с содержанием:
#!/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
Тест 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
Тест 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
Ошибки указывают, что мой Bash получил до 335.54432 МБ, прежде чем он упал. Вы можете изменить код с удвоения данных на добавление константы, чтобы получить более детальный график и точку сбоя. Но я думаю, что это должно дать вам достаточно информации, чтобы решить, волнует ли вас это. Лично я ниже 100 МБ. Ваш пробег может варьироваться.
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"(Попробуйте это на непродуктивном хосте !!;)
Обратите внимание, что это не сработает
foo=HELLO
bar=WORLD
foobar=PREFIX_$foo_$bar
как кажется, отбрасывает $ foo и оставляет вас с:
PREFIX_WORLD
но это будет работать
foobar=PREFIX_"$foo"_"$bar"
и оставить вас с правильным выводом:
PREFIX_HELLO_WORLD
Я делаю это так, когда это удобно: используйте встроенную команду!
echo "The current time is `date`"
echo "Current User: `echo $USER`"
date "+The current time is %a %b %d %Y +%T"вместо echo ...$(date). Согласно недавнему Баш, вы могли бы написать: printf "The current time is %(%a %b %d %Y +%T)T\n" -1.
На мой взгляд, самый простой способ объединить две строки - написать функцию, которая сделает это за вас, а затем использовать эту функцию.
function concat ()
{
prefix=$1
suffix=$2
echo "${prefix}${suffix}"
}
foo="Super"
bar="man"
concat $foo $bar # Superman
alien=$(concat $foo $bar)
echo $alien # Superman
Мне нравится делать быстрые функции.
#! /bin/sh -f
function combo() {
echo $@
}
echo $(combo 'foo''bar')
Еще один способ снять кожу с кошки. На этот раз с функциями: D
Я еще не знаю о PHP, но это работает в Linux Bash. Если вы не хотите влиять на переменную, вы можете попробовать это:
read pp; *# Assumes I will affect Hello to pp*
pp=$( printf $pp ;printf ' World'; printf '!');
echo $pp;
>Hello World!
Вы можете поместить другую переменную вместо «Hello» или «!». Вы также можете объединить больше строк.
foo="Hello"foo=$foo" World"echo $fooэто скорее сработало для "#! / bin / sh"