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

Это единственная вещь, которая работает для того, что мне нужно было сделать (создать виртуальную среду, затем активировать ее, а затем установить требования из сценария bash):

создать подоболочку/дочернюю оболочку из скрипта, как в:

глупый _файл.sh

(
set -o errexit
#bunch of commands
#one line fails
)

запустите дурацкий файл _с помощью:

source stupid_file.sh <file arguments here> || true

КОНЕЦ.

**поклон**

(кредит принадлежит Джеффу и Тердону)

8
21.10.2019, 10:22
5 ответов

GNU Parallel включает env_parallel. В части env_parallelперечислены все переменные для поддерживаемых оболочек.

Для bashэто код :

.
_names_of_VARIABLES() {
    compgen -A variable
}
_bodies_of_VARIABLES() {
    typeset -p "$@"
}

Таким образом, учитывая все переменные, нам нужно выяснить, какие из них установлены пользователем. Мы можем сделать это, жестко запрограммировав все переменные, установленные данной версией bash, но это не будет очень надежным доказательством будущего, потому что bashможет установить больше переменных в будущих версиях (Является ли $BASH_MYVARустановлен пользователем или будущей версией bash? ).

Вместо этого env_parallelпросит вас определить чистую среду и запустить env_parallel --sessionв ней. Это установит $PARALLEL_IGNORED_NAMESпутем перечисления имен, определенных до (с использованием кода выше ).

При последующем запуске в среде, в которой пользователь задал переменные, легко определить разницу между чистой средой и текущей средой.

env_parallel --sessionпозволяет определить чистую среду для каждого сеанса, но если вы предпочитаете иметь эталонную среду, которую можно использовать между сеансами, просто сохраните список переменных в файле.Так:

# In clean envronment
compgen -A variable > ~/.clean-env-vars

# In environment with user defined vars
compgen -A variable | grep -Fxvf ~/.clean-env-vars

Например:

#!/bin/bash

# In clean envronment
compgen -A variable > ~/.clean-env-vars

myvar=4
yourvar=3

# In environment with user defined vars
compgen -A variable | grep -Fxvf ~/.clean-env-vars

# This prints:
# myvar
# yourvar
# PIPESTATUS (which is set when running a pipe)
4
27.01.2020, 20:12

Kludgy, bash -единственное решение:

(setn(){
   set | sed '/^{/,/^}/d;/=/!d;/^BASH[A-Z_]*=\|^PPID=\|^SHLVL=\|^PIPESTATUS=\|^HISTSIZE=\|^HISTFILESIZE=\|^_[a-z_]*=/d' | sort
}
export -f setn
comm -23 <(setn) <("$BASH" -ic setn))

Возможно, вам придется также отфильтровать другие переменные с помощьюsed(или сделать шаблон BASH..более строгим ). Предполагается, что /_[a-z_]*=/исключает переменные, определяемые программируемым завершением, например _backup_globили _xspecs; это тоже можно было бы сделать более строгим.

bashвыведет значения переменных, содержащих забавные символы, в формате $'...', так что вам придется обработать это:

foo='
bar
baz
'
...
foo=$'\nbar\nbaz\n'

bashне будет создавать переменные оболочки из envvar, чьи имена содержат символы новой строки, поэтому такой трюк не может сломать этот хак.

0
27.01.2020, 20:12

В зависимости от ваших потребностей,одно простое решение может быть:

  1. Сохраните текущие переменные перед внесением изменений с помощью set > tmpили set > /tmp/current
  2. .
  3. Вы модифицируете/запускаете свое приложение
  4. Извлечь то, что было изменено с помощью diff -u <(cat tmp) <(set)или
diff -u <(cat tmp) <(set) | tail -n +3 | grep -v PIPESTATUS | grep -v "_=" | grep -E "^\+"

Где:

tail -n +3:удалить первую ненужную строку команды diff

grep -v PIPESTATUS | grep -v "_=":удалить ненужные переменные

grep -E "^\+":отображать только требуемые/необходимые изменения

Альтернатива:

diff -u <(set -o posix; set) <(bash -lc 'set -o posix; set') | grep -E "^\+"

Примечание:

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

0
27.01.2020, 20:12

I'd like to echo all self-declared variables (all non-environment variables)

Это задача для comm, как по мне:

comm -23 <( set | cut -d= -f1 | sort ) <( env | cut -d= -f1 | sort )

-23означает, что commне должен печатать столбцы 2 и 3.

3-й — это такие записи, которые находятся в обоих списках, а 2-й — это записи, которые есть только в обработанном выводе envпоста -.

Или, IOW, показывают только уникальные записи, которые были в 1-м списке .

P. S. Так как некоторые записи могут быть найдены в обоих списках сразу (проверьте их с помощью comm -12 …), вы можете также включить их в результирующий набор. Это означает, что вы не должны использовать -3в этом случае, и строки из 3-го столбца будут отображаться со смещением при печати.

0
27.01.2020, 20:12

Добавьте это в свой~/.bashrc

pre () {
    set -o posix;set > /tmp/tmp-original-envs
}

post () {
    set -o posix;set > /tmp/tmp-new-envs
    diff /tmp/tmp-original-envs /tmp/tmp-new-envs | grep -v BASH_LINENO | grep -v FUNCNAME | grep '>'
}

Затем запустите preперед вашими изменениями и postпосле

Пример:

[localhost]$ pre
[localhost]$ test=new
[localhost]$ post
> test=new
[localhost]$ 
2
27.01.2020, 20:12

Теги

Похожие вопросы