оболонка posix: друкувати список назв змінних середовища (без значень)


11

Як сумісний з posix способом, який працює з декількома реалізаціями, як я можу надрукувати список визначеної в даний час змінної середовища без їх значень?

У деяких реалізаціях (mksh, freebsd / bin / sh) exportзаконопроект підходить просто за допомогою самого себе:

$ export
FOO2
FOO

Але для деяких інших реалізацій (bash, zsh, dash) exportтакож показує значення. Наприклад, з bash:

$ export
export FOO2='as  df\
  asdk=fja:\
asd=fa\
asdf'
export FOO='sjfkasjfd  kjasdf:\
   asdkj=fkajdsf:\
       :askjfkajsf=asdfkj:\
   safdkj'
$ printenv | sed -n l
FOO2=as\tdf\$
  asdk=fja:\$
asd=fa\$
asdf$
FOO=sjfkasjfd  kjasdf:\$
   asdkj=fkajdsf:\$
\t:askjfkajsf=asdfkj:\$
   safdkj$

Інші параметри, такі як envабо printenvне мають опцій для друку лише імен змінних без значень, принаймні, не на платформах Linux та freebsd, які я пробував.

Трубопроводи до awk / sed / тощо. або обрізка списку методами розширення параметрів (наприклад, ${foo%%=*}) є прийнятною, але вона повинна працювати зі значеннями, які можуть охоплювати лінії та мати =пробіл у значенні (див. приклад вище).

Відповіді, характерні для конкретних реалізацій оболонок, цікаві, але я в першу чергу шукаю те, що сумісне в усіх реалізаціях.


2
Якщо ви збираєтеся щось проаналізувати, перейдіть до виводу, export -pякий визначено POSIX, щоб генерувати вихід, який також підходить для введення в оболонку.
Кусалаланда

Мені нічого не потрібно для введення в оболонку. Я просто хочу назвати змінні середовища. Тож зайву частину (наприклад, слово "експорт" в передній частині кожного рядка) просто потрібно було б видалити в будь-якому випадку. Чому я хотів би використовувати export -pдля цього?
Хуан

1
Ви хочете використовувати, export -pтому що це дасть вам постійний вихід на всі оболонки POSIX, які ви сказали, що хочете.
Кусалаланда

Я хочу рішення, яке буде друкувати лише імена змінних, що є послідовним рішенням у оболонках. export -pне відповідає першій вимозі - друкувати лише імена змінних без значень.
Хуан

Якщо ви збираєтеся щось розібрати, перейдіть з результатом export -p. Я не збираюся писати цей синтаксичний розбір, тому що в загальному випадку він також повинен буде зробити належний аналіз цитат, якщо у вас є змінна, значення якої чимось схоже hello\nexport var=value. Однією з небагатьох інших команд, яка дасть вам постійний вихід у всіх оболонках POSIX, є env, але цей вихід важче проаналізувати, оскільки йому бракує export =біт.
Кусалаланда

Відповіді:


9

Це дуже легко в awk.

awk 'BEGIN{for(v in ENVIRON) print v}'

Однак будьте обережні, деякі програми awk додають власні змінні середовища (наприклад, GNU awk додає AWKPATHі AWKLIBPATHв ENVIRON).

Вихід неоднозначний, якщо назва змінної середовища містить новий рядок, що є надзвичайно незвичним, але технічно можливим. Чисте рішення було б важко. Ваша найкраща ставка - почати з цього, export -pале масажувати його в чистому вигляді важко. Ви можете використовувати sed, щоб масажувати вихід export -p, а потім використовувати, evalщоб отримати оболонку, щоб видалити те, що вона цитує. Bash і zsh друкують нестандартні префікси.

report () { echo "${1%%=*}"; };
eval "$(export -p | sed "s/^export /report /;
                         s/^declare -x /report /;
                         s/typeset -x /report /")"

Зауважте, що залежно від оболонки export -pможе відображатись змінні, чиє ім’я не дійсне в оболонці, а якщо ні, то вони можуть або не можуть цитувати імена належним чином. Наприклад, dash, mksh і zsh опускають змінні, ім'я яких включає новий рядок, BusyBox dash і ksh93 друкують їх сирими, а bash друкує їх сирими без їх значення. Якщо вам потрібно захиститись від ненадійного введення, не покладайтеся на чисте рішення POSIX і, безумовно, не закликайте evalні до чого, що виходить з результатів export -p.


Я не впевнений, наскільки це "просто" з sed (1) з багаторядковими значеннями - я хотів би це побачити. Але дякую за метод awk (1). Я думаю, що це найбільш портативний спосіб поки що (хоча я не думаю, що exitце потрібно).
Хуан

Зауважте, що якщо ви отримаєте FOO<newline>BAR, ви не знаєте, чи це FOO<newline>BARзмінна середовище (яка export -pне відображатиметься з більшістю оболонок, див. env $'FOO\nBAR=test' awk 'BEGIN{for (v in ENVIRON) print v}') Або змінна a FOOі BARсередовище.
Стефан Шазелас

Зауважте, що GNU awks встановлює власні змінні середовища ( AWKPATHі AWKLIBPATHв моїй системі)
Stéphane Chazelas,

@ StéphaneChazelas - re: вбудований новий рядок у назву var - погодився - важко захищати від цього з кодом оболонки. Re: AWKPATH & AWKLIBPATH забруднення, я помітив, що підступне введення теж. Це gnu awk, не bsd awk.
Хуан

0

Мені подобаються прості речі; це працюватиме для систем POSIX:

printenv | sed 's;=.*;;' | sort
HOME
HOSTNAME
PATH
PWD
SHLVL
TERM

5
export AAA=$'multi\nBBB=line'
roaima

@todd_dsm - це не вдається для змінних середовища, які мають значення, що охоплюють більше одного рядка (наприклад, іноді TERMCAP - я бачу це, коли на екрані (1) сеанс, IIRC). Тож ця відповідь не відповідає вимогам, описаним у первісному запитанні. Мені також подобаються прості, але це взагалі не працює.
Хуан

Елементи, які ви відредагували у своєму початковому дописі, були цікавими для bash : compgen -e. Це не допомагає для мого портативного сценарію (наприклад, коли bash недоступний), але це цікаво.
Хуан

просто цікаво, навіщо обмежувати себе оболонкою бурна (posix)? бути сумісним з posix - це чудово, але ви втрачаєте велику функціональність у цій пошуці. ви можете бути портативними та НЕ сумісними з posix басом; це частина родини GNU.
todd_dsm

Використовуючи dashв debian, я отримую однакові результати з командою вище або, модифікованою printenv | sed 's;*=.;;' | sortдля отримання значень. Я експортував змінну yoі призначив їй ваш перший коментар вище; вона надрукована, як очікувалося, з кількома рядками. не впевнений, що ви переживаєте, але не повинно бути усіченого виводу. запустити команду в оболонці; що б там не було, як це має працювати; не очікуйте жодного обрізання. Потім у контексті TERMCAP / screen / iirc; повинні бути однаковими. Якщо вихід не відповідає, можливо, це проблема з однією з цих програм.
todd_dsm
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.