Подтвердить что ты не робот

Как перечислить переменные, объявленные в script в bash?

В моем script в bash есть много переменных, и я должен что-то сделать, чтобы сохранить их в файл. Мой вопрос заключается в том, как перечислить все переменные, объявленные в моем script, и получить список следующим образом:

VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi
4b9b3361

Ответ 1

set выдаст переменные, к сожалению, он также выведет также функции.

К счастью, режим POSIX выводит только переменные:

( set -o posix ; set ) | less

Трубопровод до less или перенаправление туда, где вы хотите.

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

( set -o posix ; set ) >/tmp/variables.before
source script
( set -o posix ; set ) >/tmp/variables.after
diff /tmp/variables.before /tmp/variables.after
rm /tmp/variables.before /tmp/variables.after

(Или, по крайней мере, что-то, основанное на этом:-))

Ответ 3

for i in _ {a..z} {A..Z}; do eval "echo \${[email protected]}" ; done | xargs printf "%s\n"

Это должно печатать все имена переменных оболочки. Вы можете получить список до и после поиска вашего файла, как с помощью "set", чтобы определить, какие переменные являются новыми (как объясняется в других ответах). Но имейте в виду, что такая фильтрация с diff может отфильтровывать некоторые переменные, которые вам нужны, но присутствовали до поиска вашего файла.

В вашем случае, если вы знаете, что имена ваших переменных начинаются с "VARIABLE", вы можете указать свой script и сделать:

for var in ${[email protected]}; do
   printf "%s%q\n" "$var=" "${!var}"
done

UPDATE: Для чистого решения BASH (без внешних команд):

for i in _ {a..z} {A..Z}; do
   for var in `eval echo "\\${[email protected]}"`; do
      echo $var
      # you can test if $var matches some criteria and put it in the file or ignore
   done 
done

Ответ 4

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

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

store() {
    export ${1}="${*:2}"
    [[ ${STORED} =~ "(^| )${1}($| )" ]] || STORED="${STORED} ${1}"
}

store VAR1 abc
store VAR2 bcd
store VAR3 cde

for i in ${STORED}; do
    echo "${i}=${!i}"
done

Что дает

VAR1=abc
VAR2=bcd
VAR3=cde

Ответ 5

Основываясь на некоторых из приведенных выше ответов, это сработало для меня:

before=$(set -o posix; set | sort);

исходный файл:

comm -13 <(printf %s "$before") <(set -o posix; set | sort | uniq) 

Ответ 6

Попробуйте использовать script (давайте назовем его "ls_vars" ):

  #!/bin/bash
  set -a
  env > /tmp/a
  source $1
  env > /tmp/b
  diff /tmp/{a,b} | sed -ne 's/^> //p'

chmod + x it и:

  ls_vars your-script.sh > vars.files.save

Ответ 7

С точки зрения безопасности, либо @akostadinov answer, либо @JuvenXu answer предпочтительнее полагаться на неструктурированный вывод команды set из-за следующего потенциального недостатка безопасности:

#!/bin/bash

function doLogic()
{
    local COMMAND="${1}"
    if ( set -o posix; set | grep -q '^PS1=' )
    then
        echo 'Script is interactive'
    else
        echo 'Script is NOT interactive'
    fi
}

doLogic 'hello'   # Script is NOT interactive
doLogic $'\nPS1=' # Script is interactive

В приведенной выше функции doLogic используется set для проверки наличия переменной PS1, чтобы определить, является ли script интерактивным или нет (неважно, является ли это наилучшим способом достижения этой цели; просто пример.)

Однако вывод set неструктурирован, что означает, что любая переменная, содержащая новую строку, может полностью загрязнить результаты.

Это, конечно, потенциальный риск для безопасности. Вместо этого используйте поддержку Bash для расширения имени косвенной переменной или compgen -v.

Ответ 8

Попробуйте следующее: set | egrep "^\w+=" (с трубопроводом | less или без него)

Первое предлагаемое решение ( set -o posix ; set ) | less работает, но имеет недостаток: он передает управляющие коды терминалу, поэтому они отображаются неправильно. Например, если есть (вероятно) переменная IFS=$' \t\n', мы можем видеть:

IFS='
'

... вместо этого.

My egrep решение отображает это (и в конечном итоге другие аналогичные) правильно.

Ответ 9

Я, вероятно, недавно украл ответ... в любом случае немного отличается как func:

    ##
    # usage source bin/nps-bash-util-funcs
    # doEchoVars
    doEchoVars(){

        # if the tmp dir does not exist
        test -z ${tmp_dir} && \
        export tmp_dir="$(cd "$(dirname $0)/../../.."; pwd)""/dat/log/.tmp.$$" && \
        mkdir -p "$tmp_dir" && \
        ( set -o posix ; set )| sort >"$tmp_dir/.vars.before"


        ( set -o posix ; set ) | sort >"$tmp_dir/.vars.after"
        cmd="$(comm -3 $tmp_dir/.vars.before $tmp_dir/.vars.after | perl -ne 's#\s+##g;print "\n $_ "' )"
        echo -e "$cmd"
    }