Чи може назва змінної оболонки включати дефіс або тире (-)?


38

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

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

$export a_b=c

Перший кидає задану помилку, а другий чудово працює.



Оболонки зазвичай не дозволяють назви таких змінних. Вам доведеться обійти оболонку, можливо навіть за допомогою спеціальної програми C, що завантажує змінні в середовище вашої команди. Ви не можете виправити цю невдачу (навіть можливий ризик безпеки)?
vonbrand

Відповіді:


47

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

Якщо у вас є програма, яка потребує змінної середовища, яка не відповідає обмеженням оболонки, запустіть її з envпрограмою.

env 'strange-name=some value' myprogram

Зауважте, що деякі оболонки (наприклад, сучасний тире , 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 Це правда, що деякі речі, які раніше працювали, можуть більше не працювати: з моменту обстрілу люди стали більш консервативними щодо імен змінних, і тире насправді змінилося з моменту написання цієї відповіді (не як наслідок Shellshock, хоча, але щоб уникнути помилок по тих же лініях). Я додав замітку до своєї відповіді.
Жил "ТАК - перестань бути злим"

15

Це неможливо в Bash.

З розділу " Визначення " на сторінці керівництва bash:

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

З розділу Параметри на сторінці керівництва bash:

Параметр - це сутність, яка зберігає значення. Це може бути ім'я, число чи один із спеціальних символів, перелічених нижче у Спеціальних параметрах. Змінна - це параметр, позначений іменем.


2
+1 за демонстрацію корисності сторінок man
ktf

2
Старий пост, який я знаю, але хочу зазначити, що сторінки для новоприбулих людей можуть бути досить виразними. У мене ще є часи, коли мені потрібно розшукувати кращі пояснення / приклади. Хтось бреше, якби вони сказали, що цього ніколи не траплялося.
TCZ8

1
@ TCZ8 Єдині люди, які сказали мені, що вони думали, що сторінки чоловіка є «криптовалютними» - це такі ж люди, які не читають повідомлень про помилки і просто скупо читають усе, пропускаючи прямо те, що їм потрібно читати.
Майлз Рут

13

Ви можете отримати доступ до дефісної змінної за допомогою непрямої посилання.

$ env 'my-hyphenated-variable=hello' /bin/bash
$ name='my-hyphenated-variable'
$ echo ${!name}
hello

1
Я ніколи не чув про цю функціональність, поки не прочитав цей коментар. Надав для мене набагато простіше рішення, ніж прийняту відповідь.
DrStrangepork

7
Така поведінка була відключена в нових версіях bash. Дивіться stackoverflow.com/questions/36989263/… для ретельного аналізу ситуації.
Nicolas Dudebout

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'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.