Вероятно, это хорошо, чтобы привыкнуть вставлять $fooдвойные кавычки, для тех случаев, когда это действительно имеет значение.
Каскабель
104
Нас учат всегда делать это, потому что, когда происходит замена, оболочки будут игнорировать пробелы, но двойные кавычки всегда будут защищать эти пробелы.
Клубника
62
Должен ли быть пробел в вашем первом примере? Можно ли сделать что-то подобное foo="$fooworld"? Я бы предположил, что нет ...
безразлично
341
@nonsensickle Это будет искать переменную с именем fooworld. foo="${foo}world"
Устранение неоднозначности,
4
@ JVE999 Да, это тоже работает, хотя, на мой взгляд, это не так хорошо для ясности кода ... Но это может быть моим предпочтением ... Есть пара других способов, которыми это можно сделать - дело в том, убедитесь, что имя переменной отделено от частей без имени переменной, чтобы она анализировалась правильно.
Твальберг
1128
Bash также поддерживает +=оператор, как показано в этом коде:
Могу ли я использовать этот синтаксис с ключевым словом экспорта? например export A+="Z"или, может быть, Aпеременную нужно экспортировать только один раз?
Levesque
3
@levesque: оба :-). Переменные нужно экспортировать только один раз, но export A+=Zэто тоже очень хорошо работает.
Thkala
38
Поскольку это bashism, я думаю, стоит упомянуть, что вы никогда не должны использовать #!/bin/shв сценарии, использующем эту конструкцию.
Score_Under
2
Это конкретно и только оператор плюс-равно. То есть, в отличие от Javascript, в Bash эхо $ A + $ B печатает "X Y + Z"
phpguru
6
Башизм - это функция оболочки, которая поддерживается только в bashнекоторых и более продвинутых оболочках. Он не будет работать busybox shни с dash( или (что /bin/shна многих дистрибутивах)), ни с некоторыми другими оболочками, такими как /bin/shпредоставленные во FreeBSD.
Score_Under
961
Баш первый
Поскольку этот вопрос предназначен специально для Bash , моя первая часть ответа представит различные способы сделать это правильно:
+=: Добавить к переменной
Синтаксис +=может использоваться по-разному:
Добавить к строке var+=...
(Потому что я скромный, я буду использовать только две переменные fooи aзатем повторно использовать то же самое в целом ответ ;-).
a=2
a+=4
echo $a
24
Используя синтаксис вопроса Stack Overflow ,
foo="Hello"
foo+=" World"
echo $foo
HelloWorld
работает отлично!
Добавить к целому числу ((var+=...))
переменная a- это строка, но также целое число
echo $a
24((a+=12))
echo $a
36
Добавить в массив var+=(...)
Наш aмассив также состоит только из одного элемента.
Обратите внимание, что между скобками находится разделенный пробелами массив . Если вы хотите сохранить строку, содержащую пробелы в вашем массиве, вы должны заключить их:
a+=(one word "hello world!")
bash:!": event not found
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[@]}3618 one word hello world! hello world! hello world!
В этом массиве семь строк . Таким образом, мы можем построить отформатированную строку, содержащую ровно семь позиционных аргументов:
Nota: Использование двойных кавычек может быть полезно для работы со строками , которые содержат spaces, tabulationsи / илиnewlines
printf -v foo "%s World""$foo"
Shell сейчас
В оболочке POSIX вы не можете использовать bashisms , поэтому нет встроенныхprintf .
В принципе
Но вы могли бы просто сделать:
foo="Hello"
foo="$foo World"
echo $foo
HelloWorld
Отформатирован с использованием разветвленногоprintf
Если вы хотите использовать более сложные конструкции, вы должны использовать форк (новый дочерний процесс, который выполняет задание и возвращает результат через stdout):
+=Оператор также намного быстрее , чем $a="$a$b"в моих тестах .. Какой смысл.
Мэтт
7
Этот ответ потрясающий, но я думаю, что он пропускает var=${var}.shпример из других ответов, что очень полезно.
Генераорама
1
Является bashединственная оболочка с +=оператором? Я хочу посмотреть, достаточно ли она портативна
dashesy
1
@dashesy нет. это, конечно, не единственная оболочка с +=оператором, но все эти способы - башмы , поэтому не переносимы! Даже вы можете столкнуться со специальной ошибкой в случае неправильной версии bash!
Хотя специальные символы и пробелы не используются, двойные кавычки, кавычки и фигурные скобки бесполезны: var=myscript;var=$var.sh;echo $varбудут иметь те же эффекты (это работает в bash, dash, busybox и других).
Ф. Хаури
@ Ф.Хаури, спасибо, что указал на это. Но если вы добавите число, оно не будет работать: например echo $var2, не производитmyscript2
Pynchia
@Pynchia Эта работа из-за .недопустимой точки в имени переменной. Если еще echo ${var}2или посмотри мой ответ
Ф. Хаури
119
bla=hello
laber=kthx
echo "${bla}ohai${laber}bye"
Будет выходной
helloohaikthxbye
Это полезно, когда
$blaohai
приводит к ошибке переменной not found. Или если у вас есть пробелы или другие специальные символы в ваших строках. "${foo}"правильно избегает всего, что вы положили в него.
... следовательно ${a}\ WorldпроизводитHello World
XavierStuvw
Это удивляет меня; Я бы ожидал c=$a$bздесь сделать то же самое, что c=$a World(который будет пытаться запускаться Worldкак команда). Я предполагаю, что это означает, что присвоение анализируется до
раскрытия
31
Вот краткое резюме того, о чем говорит большинство ответов.
Допустим, у нас есть две переменные и $ 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
Несколько заметок:
Заключение RHS присвоения в двойные кавычки, как правило, является хорошей практикой, хотя во многих случаях оно является необязательным.
+= лучше с точки зрения производительности, если большая строка строится с небольшими приращениями, особенно в цикле
использовать {}вокруг имен переменных, чтобы устранить неоднозначность их расширения (как в строке 2 в таблице выше). Как видно из строк 3 и 4, в этом нет необходимости, {}если переменная не конкатенируется со строкой, которая начинается с символа, который является допустимым первым символом в имени переменной оболочки, то есть является алфавитом или подчеркиванием.
Это то, что я сделал, и я нашел это намного проще и понятнее, чем другие ответы. Есть ли причина, по которой никто в ответах с наибольшим количеством голосов не указал этот вариант?
Quimnuss
1
@quimnuss Тот факт, что строки не соответствуют тем, которые используются в вопросе OP, может быть хорошей причиной.
июля
20
Если вы хотите добавить что-то вроде подчеркивания, используйте escape (\)
Или, альтернативно, $ {FILEPATH} _ $ DATEX. Здесь {} используются для обозначения границ имени переменной. Это приемлемо, потому что подчеркивание является допустимым символом в именах переменных, поэтому в вашем фрагменте bash фактически пытается разрешить FILEPATH_, а не только $ FILEPATH
Nik O'Lai
1
для меня у меня была одна переменная, т. е. $ var1 и константа рядом с ней, поэтому echo $ var1_costant_traling_part работает для меня
YouAreAwesome
2
Я думаю, что для побега нужна только одна обратная реакция: echo $a\_$bбудет. Как намекает в комментарии Ник О'Лай, подчеркивание является регулярным символом. Обработка пробелов намного более чувствительна к строкам, эхо и конкатенации - \ этот поток можно использовать и внимательно читать, так как эта проблема возникает время от времени.
Синтаксис первого блока сбивает с толку. Что означают эти знаки $?
XavierStuvw
15
Даже если теперь разрешен оператор + =, он был введен в Bash 3.1 в 2004 году.
Любой сценарий, использующий этот оператор в старых версиях Bash, завершится с ошибкой «команда не найдена», если вам повезет, или с «синтаксической ошибкой рядом с неожиданным токеном».
Для тех, кому небезразлична обратная совместимость, придерживайтесь старых стандартных методов конкатенации Bash, таких как упомянутые в выбранном ответе:
Точка строк с пробелом, которые читаются как команда, отображается в точке определения. Так d=DD DDчто дайте DD: command not found--- обратите внимание, что это последний DD, а скорее d, который не найден. Если все операнды правильно отформатированы и уже содержат необходимые пробелы, вы можете просто объединить их s=${a}${b}${c}${d}; echo $sс меньшим количеством кавычек. Также вы можете использовать \ (экранированный пробел), чтобы избежать этих проблем - d=echo\ echoне будет запускать эхо-вызов, тогда как d=echo echoбудет.
XavierStuvw
7
Есть один конкретный случай, когда вы должны позаботиться:
Это работает, но иногда дает непредсказуемые результаты, потому что интерполяция переменных не защищена. Таким образом, вы не можете полагаться на эту форму для всех случаев использования.
Энтони Ратледж,
5
Если это как ваш пример добавления " World"к исходной строке, то это может быть:
Ошибки указывают, что мой Bash получил до 335.54432 МБ, прежде чем он упал. Вы можете изменить код с удвоения данных на добавление константы, чтобы получить более детальный график и точку сбоя. Но я думаю, что это должно дать вам достаточно информации, чтобы решить, волнует ли вас это. Лично я ниже 100 МБ. Ваш пробег может варьироваться.
это происходит потому, что подчеркивание является допустимым символом в именах переменных, поэтому bash видит foo_ как переменную. Когда необходимо указать bash точные границы имени переменной, можно использовать фигурные скобки: PREFIX _ $ {foo} _ $ bar
На 1-й строке вы можете сбросить вилку , используя:, 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.
Ф. Хаури
1
На мой взгляд, самый простой способ объединить две строки - написать функцию, которая сделает это за вас, а затем использовать эту функцию.
foo="Hello"
foo=$foo" World"
echo $foo
это скорее сработало для "#! / bin / sh"foo1="World" foo2="Hello" foo3="$foo1$foo2"
Ответы:
В общем, для объединения двух переменных вы можете просто записать их одну за другой:
источник
$foo
двойные кавычки, для тех случаев, когда это действительно имеет значение.foo="$fooworld"
? Я бы предположил, что нет ...fooworld
.foo="${foo}world"
Bash также поддерживает
+=
оператор, как показано в этом коде:источник
export A+="Z"
или, может быть,A
переменную нужно экспортировать только один раз?export A+=Z
это тоже очень хорошо работает.#!/bin/sh
в сценарии, использующем эту конструкцию.bash
некоторых и более продвинутых оболочках. Он не будет работатьbusybox sh
ни сdash
( или (что/bin/sh
на многих дистрибутивах)), ни с некоторыми другими оболочками, такими как/bin/sh
предоставленные во FreeBSD.Баш первый
Поскольку этот вопрос предназначен специально для Bash , моя первая часть ответа представит различные способы сделать это правильно:
+=
: Добавить к переменнойСинтаксис
+=
может использоваться по-разному:Добавить к строке
var+=...
(Потому что я скромный, я буду использовать только две переменные
foo
иa
затем повторно использовать то же самое в целом ответ ;-).Используя синтаксис вопроса Stack Overflow ,
работает отлично!
Добавить к целому числу
((var+=...))
переменная
a
- это строка, но также целое числоДобавить в массив
var+=(...)
Наш
a
массив также состоит только из одного элемента.Обратите внимание, что между скобками находится разделенный пробелами массив . Если вы хотите сохранить строку, содержащую пробелы в вашем массиве, вы должны заключить их:
Хм .. это не ошибка, а особенность ... Чтобы предотвратить попытки разработки bash
!"
, вы можете:printf
: Перестроить переменную с помощью встроенной командыprintf
Встроенная команда дает мощный способ рисования формат строки. Поскольку это встроенная функция Bash , существует возможность отправки отформатированной строки в переменную вместо печати наstdout
:В этом массиве семь строк . Таким образом, мы можем построить отформатированную строку, содержащую ровно семь позиционных аргументов:
Или мы могли бы использовать одну строку формата аргумента, которая будет повторяться столько же аргументов, сколько представлено ...
Обратите внимание, что наше
a
все еще массив! Только первый элемент изменен!В bash, когда вы обращаетесь к имени переменной без указания индекса, вы всегда обращаетесь только к первому элементу!
Таким образом, чтобы получить наш массив из семи полей, нам нужно только переустановить 1-й элемент:
Строка формата с одним аргументом и многими аргументами:
Использование синтаксиса вопроса переполнения стека :
Nota: Использование двойных кавычек может быть полезно для работы со строками , которые содержат
spaces
,tabulations
и / илиnewlines
Shell сейчас
В оболочке POSIX вы не можете использовать bashisms , поэтому нет встроенных
printf
.В принципе
Но вы могли бы просто сделать:
Отформатирован с использованием разветвленного
printf
Если вы хотите использовать более сложные конструкции, вы должны использовать форк (новый дочерний процесс, который выполняет задание и возвращает результат через
stdout
):Исторически, вы могли использовать обратные пометки для получения результата форка :
Но это не легко для вложения :
с обратными чертами вы должны избегать внутренних вилок с обратными слешами :
источник
+=
Оператор также намного быстрее , чем$a="$a$b"
в моих тестах .. Какой смысл.var=${var}.sh
пример из других ответов, что очень полезно.bash
единственная оболочка с+=
оператором? Я хочу посмотреть, достаточно ли она портативна+=
оператором, но все эти способы - башмы , поэтому не переносимы! Даже вы можете столкнуться со специальной ошибкой в случае неправильной версии bash!Ты тоже можешь это сделать:
источник
var=myscript;var=$var.sh;echo $var
будут иметь те же эффекты (это работает в bash, dash, busybox и других).echo $var2
, не производитmyscript2
.
недопустимой точки в имени переменной. Если ещеecho ${var}2
или посмотри мой ответБудет выходной
Это полезно, когда
$blaohai
приводит к ошибке переменной not found. Или если у вас есть пробелы или другие специальные символы в ваших строках."${foo}"
правильно избегает всего, что вы положили в него.источник
источник
Я бы решил проблему просто
Например,
который производит
Если вы попытаетесь объединить строку с другой строкой, например,
потом
echo "$c"
будет производитьс дополнительным пространством.
не работает, как вы можете себе представить, но
производит
источник
${a}\ World
производитHello World
c=$a$b
здесь сделать то же самое, чтоc=$a World
(который будет пытаться запускатьсяWorld
как команда). Я предполагаю, что это означает, что присвоение анализируется доВот краткое резюме того, о чем говорит большинство ответов.
Допустим, у нас есть две переменные и $ 1 установлен на «один»:
Таблица ниже объясняет различные контексты, в которых мы можем комбинировать значения
a
иb
создавать новую переменнуюc
.Несколько заметок:
+=
лучше с точки зрения производительности, если большая строка строится с небольшими приращениями, особенно в цикле{}
вокруг имен переменных, чтобы устранить неоднозначность их расширения (как в строке 2 в таблице выше). Как видно из строк 3 и 4, в этом нет необходимости,{}
если переменная не конкатенируется со строкой, которая начинается с символа, который является допустимым первым символом в имени переменной оболочки, то есть является алфавитом или подчеркиванием.Смотрите также:
источник
источник
Еще один подход ...
... и еще один.
источник
Если вы хотите добавить что-то вроде подчеркивания, используйте escape (\)
Это не работает:
Это прекрасно работает:
источник
echo $a\_$b
будет. Как намекает в комментарии Ник О'Лай, подчеркивание является регулярным символом. Обработка пробелов намного более чувствительна к строкам, эхо и конкатенации -\
этот поток можно использовать и внимательно читать, так как эта проблема возникает время от времени.Самый простой способ с кавычками:
источник
var=$B$b"a"; echo Hello\ $var
сделал бы, я верюВы можете объединить без кавычек. Вот пример:
Это последнее утверждение напечатало бы "OpenSystems" (без кавычек).
Это пример скрипта Bash:
источник
Даже если теперь разрешен оператор + =, он был введен в Bash 3.1 в 2004 году.
Любой сценарий, использующий этот оператор в старых версиях Bash, завершится с ошибкой «команда не найдена», если вам повезет, или с «синтаксической ошибкой рядом с неожиданным токеном».
Для тех, кому небезразлична обратная совместимость, придерживайтесь старых стандартных методов конкатенации Bash, таких как упомянутые в выбранном ответе:
источник
Я предпочитаю использовать фигурные скобки
${}
для расширения переменной в строке:Вьющиеся скобки подойдут для непрерывного использования строки:
В противном случае использование
foo = "$fooWorld"
не будет работать.источник
Если вы пытаетесь разделить строку на несколько строк, вы можете использовать обратную косую черту:
С одним пробелом между:
Этот также добавляет только один пробел между:
источник
Более безопасный способ:
Строки, содержащие пробелы, могут стать частью команды, используйте «$ XXX» и «$ {XXX}», чтобы избежать этих ошибок.
Плюс взгляните на другой ответ о + =
источник
d=DD DD
что дайтеDD: command not found
--- обратите внимание, что это последний DD, а скорее d, который не найден. Если все операнды правильно отформатированы и уже содержат необходимые пробелы, вы можете просто объединить ихs=${a}${b}${c}${d}; echo $s
с меньшим количеством кавычек. Также вы можете использовать\
(экранированный пробел), чтобы избежать этих проблем -d=echo\ echo
не будет запускать эхо-вызов, тогда какd=echo echo
будет.Есть один конкретный случай, когда вы должны позаботиться:
Будет выводить
"daniel"san
, а не такdanielsan
, как вы, возможно, хотели. В этом случае вы должны сделать вместо этого:источник
Вот как вы объединяете две строки.
источник
Если это как ваш пример добавления
" World"
к исходной строке, то это может быть:Выход:
источник
источник
var3=$var1\ $var2
имеет тот же эффектЕсть высказанные опасения по поводу производительности, но данные не предлагаются. Позвольте мне предложить простой тест.
(ПРИМЕЧАНИЕ:
date
на macOS не предлагает наносекунд, поэтому это должно быть сделано на Linux.)Я создал append_test.sh на GitHub с содержанием:
Тест 1:
Тест 2:
Ошибки указывают, что мой 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 и оставляет вас с:
но это будет работать
и оставить вас с правильным выводом:
источник
Вот один через AWK :
источник
Я делаю это так, когда это удобно: используйте встроенную команду!
источник
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
.На мой взгляд, самый простой способ объединить две строки - написать функцию, которая сделает это за вас, а затем использовать эту функцию.
источник
Мне нравится делать быстрые функции.
Еще один способ снять кожу с кошки. На этот раз с функциями: D
источник
Я еще не знаю о PHP, но это работает в Linux Bash. Если вы не хотите влиять на переменную, вы можете попробовать это:
Вы можете поместить другую переменную вместо «Hello» или «!». Вы также можете объединить больше строк.
источник