Может ли имя переменной оболочки включать дефис или тире (-)?

38

Я не могу использовать -в переменных в оболочке. Есть ли способ, чтобы иметь возможность использовать его, потому что у меня есть один скрипт, который зависит от таких именованных переменных:

$export a-b=c
-bash: export: `a-b=c': not a valid identifier

$export a_b=c

Первый выдает данную ошибку, а второй работает нормально.

хуг
источник
возможный межсайтовый дубликат: stackoverflow.com/questions/2821043/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
Оболочки обычно не допускают таких имен переменных. Вам придется обойти оболочку, возможно, даже с пользовательской программой C, загружающей переменные в среду вашей команды. Не можете ли вы исправить эту ошибку (даже возможный риск безопасности)?
vonbrand

Ответы:

47

Я никогда не встречал оболочку в стиле Борна, которая допускала -бы имя переменной. _Поддерживаются только буквы ASCII (в любом случае) и цифры, и первый символ не должен быть цифрой.

Если у вас есть программа, для которой требуется переменная среды, которая не соответствует ограничениям оболочки, запустите ее вместе с envпрограммой.

env 'strange-name=some value' myprogram

Обратите внимание, что некоторые оболочки (например, современные dash , mksh, zsh) удаляют переменные, имена которых им не нравятся, из среды. ( Shellshock заставил людей быть более осторожными в отношении имен переменных среды, поэтому ограничения, вероятно, со временем станут более жесткими, а не более жесткими.) Поэтому, если вам нужно передать в программу переменную, имя которой содержит специальный символ, передайте ее напрямую, без оболочки между ( env 'strange-name=some value' sh -c'…; myprogram'может или не может работать).

Жиль "ТАК - прекрати быть злым"
источник
Больше не работает.
Джесси Глик
4
@JesseGlick Да, это так. (Ваш комментарий будет полезно , если вы определили «не работает»: с тем, что данные , что эффект вместо желаемого эффекта , и если вы сказали , какая реализация? envВас используется на какой операционной системе.)
Жиля SO- остановка существо зло '
Сожалею. Ubuntu Yakkety со всеми обновлениями, envиз coreutils, shиз dash: env 'with-dashes=value' bash -c 'env | fgrep dashes'работает, но env 'with-dashes=value' sh -c 'env | fgrep dashes'ничего не печатает. То есть envсамо по себе хорошо, но Dash, кажется, специально блокирует эти переменные. Таким образом, если рассматриваемая программа запускается через оболочку оболочки с типичным #!/bin/shзаголовком, нет очевидного способа передачи таких переменных. пример обходного решения
Джесси Глик
@JesseGlick Это черта, удаляющая переменную. Вы должны использовать envближе к вызывающему сайту программы, которая нуждается в этом имени переменной, без оболочки между ними. Dash не одинок в удалении переменных, чье имя ему не нравится.
Жиль "ТАК - перестань быть злым"
1
@JesseGlick Это правда, что некоторые вещи, которые раньше работали, могут больше не работать, хотя: с момента шеллшока люди стали более консервативны в отношении имен переменных, и черта действительно изменилась с тех пор, как я написал этот ответ (хотя не как следствие Шеллшока, но чтобы избежать ошибки в том же духе). Я добавил примечание к своему ответу.
Жиль "ТАК - перестань быть злым"
15

Это невозможно в Баше.

Из раздела « Определения » на странице руководства bash:

name Слово, состоящее только из буквенно-цифровых символов и символов подчеркивания и начинающееся с буквенного символа или символа подчеркивания. Также называется идентификатором.

Из раздела « Параметры » на странице руководства bash:

Параметр - это объект, который хранит значения. Это может быть имя, число или один из специальных символов, перечисленных ниже в разделе «Специальные параметры». Переменная - это параметр, обозначаемый именем.

Lekensteyn
источник
2
+1 за демонстрацию полезности man-страниц еще раз
ktf
2
Старый пост я знаю, но хочу отметить, что для новичков справочные страницы могут быть довольно загадочными. У меня все еще есть времена, когда мне нужно искать лучшие объяснения / примеры. Любой будет лгать, если они скажут, что с ними этого никогда не случалось.
TCZ8
1
@ TCZ8 Единственные люди, которые сказали мне, что считали man-страницы «загадочными», - это те же люди, которые не читают сообщения об ошибках и просто читают все, пропуская все, что им нужно для чтения.
Майлз Рут
13

Вы можете получить доступ к дефисной переменной, используя косвенную ссылку.

$ env 'my-hyphenated-variable=hello' /bin/bash
$ name='my-hyphenated-variable'
$ echo ${!name}
hello
Джон Нэлли
источник
1
Я никогда не слышал об этой функции, пока не прочитал этот комментарий. Предоставил мне гораздо более простое решение, чем принятый ответ.
DrStrangepork
7
Это поведение было отключено в новых версиях bash. См. Stackoverflow.com/questions/36989263/… для подробного анализа ситуации.
Николас Дудебо
6

Если ваш сценарий зависит от наличия в именах переменных дефисов, это ошибка программирования. Если вам это удобно из-за того, что инструменты, которые вы регулярно используете, чтобы имена переменных содержали дефис, вам, возможно, придется изучить больше и другие инструменты.

Вы пытались использовать tr для преобразования дефисов в подчеркивания?

hyphenated_name="a-b"
unhyphenated_name=$(echo $hyphenated_name | tr '-' '_')
declare -x $unhyphenated_name="some value"

Bash позволяет '-' появляться в именах функций. Я делаю это все время. Например:

function foo-bar() {
   echo "$@"
}
Брайан Дж. Фокс
источник
2

Символ dash ( -) является символом разрыва и не допускается как часть имен переменных. Есть способы взломать это с помощью указанных в кавычках переменных, но их разбор действительно проблематичен. Есть и другие символы со специальным значением в контексте имен переменных в bash, в частности, фигурные скобки, скобки, операторные символы и кавычки. (например, {}()=+-&'"и больше)

Я бы предположил, что практически вам нужно найти другую парадигму для построения вашего сценария. Возможно, у вас есть идея о «именах переменных переменных» из других языков. Как правило, это не очень хорошая идея в сценариях оболочки.

Если вы отредактируете это или зададите новый вопрос с подробной информацией о вашем контексте и о том, что вы пытаетесь достичь, мы могли бы предложить хороший способ написания сценария.

Калеб
источник
2

Руководство Bash определяет «имя» как:

«Слово», состоящее только из букв, цифр и символов подчеркивания и начинающееся с буквы или символа подчеркивания. «Имена используются как имена переменных и функций оболочки. Также называется «идентификатором».

Таким образом, вы не можете использовать дефис в имени.

Майкл Хоффман
источник
0

Большинство оболочек поддерживают только имена переменных az, AZ, 0-9 и _. Прочитайте второй пункт на этой странице .


источник
0

Вы можете играть с env и sed.

В качестве примера мне нужно было прочитать эту переменную 'ELASTICSEARCH_CLUSTER-NODES'.
Команда env выведет это:

~ $ env
ELASTICSEARCH_CLUSTER-NODES=elasticsearch:9200
JAVA_ALPINE_VERSION=8.212.04-r0
HOSTNAME=17eb9e7fec4c
...

Итак, чтобы извлечь переменную:

ESHOST=`env | sed -n 's/ELASTICSEARCH_CLUSTER-NODES=\(.*\)/\1/p'`
Гийом Парамель
источник
-1

Я считаю, что только переменные bash допускаются только буквы, цифры и подчеркивание. Это имеет место во многих языках программирования (исключение составляет JavaScript).

Я не рекомендую, чтобы ваш скрипт зависел от этих типов имен переменных.

На самом деле, вы должны попытаться запрограммировать таким образом, чтобы вы могли заменить имена переменных другими именами, и это не имеет значения. Как правило, имена переменных должны описывать, что содержит переменная. Это значительно облегчает отладку; если не для вас, то для следующего разработчика, который пытается выяснить код.


источник
-1

Вы можете использовать envкоманду для установки и сброса переменных окружения с помощью хифенов "-".

Для установки необходимо использовать окр запустить команду: env command. Вы передаете переменные следующим образом:

env a-b=c command

Посмотрите, как это работает с:

env a-b=c env

или чтобы было понятнее:

env a-b=c env|grep 'a-b'
Невиш
источник