Навпроти команди "source"


9

Я використовую sourceкоманду в моєму скрипті bash для того, щоб прочитати / надрукувати значення змінних

more linuxmachines_mount_point.txt

export linuxmachine01="sdb sdc sdf sdd sde sdg"
export linuxmachine02="sde sdd sdb sdf sdc"
export linuxmachine03="sdb sdd sdc sde sdf"
export linuxmachine06="sdb sde sdf sdd"

source  linuxmachines_mount_point.txt

echo $linuxmachine01
sdb sdc sdf sdd sde sdg

У чому полягає протилежність sourceдля скасування змінних?

Очікувані результати

echo $linuxmachine01

< no output >

14
Це не sourceвстановлення змінних у вашому оточенні, а exportвисловлювання у файлі, який ви source. Отже , якщо у вас інший файл, який має однакові змінні, sourceможе бути навпаки . sourcesourceunset
user4556274

2
yael, не використовуй експорт, просто використовуй name = "val". Експорт призначений для змінних сценаріїв до бінарних файлів (оточення).
ctrl-d


2
Це неможливо. Концепція, яку ви шукаєте, називається реверсивними обчисленнями . Мови програмування повинні бути спеціально розроблені з деякими суворими обмеженнями, щоб бути оборотними. Bash не є однією з таких мов програмування.
Jörg W Mittag

1
@yael, це неправда (і ви, очевидно, ніколи не проходили тест, про який ви говорите ctrl-d); тобі абсолютно не потрібні export. Все exportце - скопіювати значення в середовище, але вони є перемінними оболонками, незалежно від того, вони також визначені як змінні середовища. Крім того, визначення непотрібних змінних середовищ скорочує вашу максимальну довжину командного рядка, оскільки вони зберігаються в одному і тому ж (обмеженому!) Просторі в процесі.
Чарльз Даффі

Відповіді:


21

Використання передплати (рекомендується)

Запустіть початкову команду в нижній частині:

(
source linuxmachines_mount_point.txt
cmd1 $linuxmachine02
other_commands_using_variables
etc
)
echo $linuxmachine01  # Will return nothing

Подоболочкі визначаються круглі дужки: (...). Будь-які змінні оболонки, встановлені в підшалі, забуваються після закінчення нижньої оболонки.

Використання невстановлених

Це скидає будь-яку змінну, експортовану linuxmachines_mount_point.txt:

unset $(awk -F'[ =]+' '/^export/{print $2}' linuxmachines_mount_point.txt)
  • -F'[ =]+' говорить awk використовувати будь-яку комбінацію пробілів та рівних знаків як роздільник поля.

  • /^export/{print $2}

    Це говорить awk, щоб вибрати рядки, які починаються з, exportа потім надрукувати друге поле.

  • unset $(...)

    Це запускає команду всередині $(...), фіксує її stdout та знімає будь-які змінні, названі його результатом.


чому б не використати це - for i in `awk '{print $ 2}' файл | awk -F "=" '{print $ 1}' `; зробіть невстановлене $ i; зробили? (простіше для невстановлених)
yael

2
@yael Для використання додаткового процесу та циклу, коли вони не потрібні. Думки можуть відрізнятися, але я не вважаю це простішим. Крім того, і потенційно небезпечний, він передбачає, що кожен рядок в fileекспортній заяві.
John1024

8
@yael Крім того, для встановлення змінних змін та скасування інших побічних ефектів коду саме те, для чого призначені додаткові оболонки. Вони роблять це просто і надійно. Якщо немає іншої особливої ​​причини, інакше, те, що вам слід використовувати.
John1024

4

Ви не можете скасувати sourceсценарій.

Що ви можете зробити, це зберегти всі експортовані змінні у тимчасовому файлі, порівняти їх із змінними після отримання скрипту, а потім видалити переповнення unset, наприклад:

export > temp_file
source myscript

#... do some stuff

unset "$(comm -3 <(sort temp_file) <(export | sort) | awk -F'[ =]' '{print $3}' | tr '\n' ' ')"

чому б не використати це - for i in `awk '{print $ 2}' файл | awk -F "=" '{print $ 1}' `; зробіть невстановлене $ i; зробили? (простіше для невстановлених)
yael

@yael це буде працювати лише в тому випадку, якщо сценарій містить тільки exports.
jimmij

що ви маєте на увазі "експортувати s", мій файл включає linuxmachine01 = "sdb sdc sdf sdd sde sdg" і так далі, і коли я використовую цикл awk, його без проблем
скасуйте

@yael Я не знаю, як саме виглядає ваш файл, тому я дав загальну відповідь, наприклад, що, якщо сценарій містить коментар вгорі, що говорить "# Ось декілька змінних для експорту з точками монтування".
jimmij

2

Ви можете використовувати unsetкоманду для "забуття" змінних.


файл може бути з різними машинами, тож як скинути другу змінні у файлі?
yael

unset змінної забуде це (ви можете знайти це пояснено на сторінці bash / sh / ksh / zsh man) демонстрація цього: pastebin.com/MGQyTZEA
francois P

так, але тому що змінні можуть бути різними, скрипт bash потрібно зробити це, прочитавши змінну з файлу та скасуйте їх, він не може бути статичним, оскільки змінна невідома
yael

потім зніміть ваші експортні рядки (виріжте), щоб перелічити змінні з файлу, який слід скасувати експортувати linuxmachine06 = "sdb sde sdf sdd", тоді ви отримаєте linuxmachine06 як ім'я для скасування прикладу: pastebin.com/M9eCtLc7, як ви бачите команду unset тут doen Не знаю назви змінної, вона відома лише наприкінці
Франсуа П

ОК, я буду використовувати цей синтаксис для скасування - для я у файлі `awk '{print $ 2}' | awk -F "=" '{print $ 1}' `; зробіть невстановлене $ i; зроблено
yael

2

Найпростіше рішення отримати очікуваний результат (нічого) - повторно оголосити змінну порожньою:

$ export linuxmachine01="sdb sdc sdf sdd sde sdg"
$ echo "$linuxmachine01"
sdb sdc sdf sdd sde sdg

$ linuxmachine01=""
$ echo "$linuxmachine01"
$

Звичайно, змінна все ще визначена (і експортується), порожня, але визначена:

$ declare -p linuxmachine01
declare -x linuxmachine01=""

Щоб правильно видалити змінну як із середовища, так і з запущеної оболонки, слід використовувати unset (рекомендований спосіб):

$ unset linuxmachine01
$ declare -p linuxmachine01
bash: declare: linuxmachine01: not found
$ echo "$linuxmachine01"
$

1

Найпростіший спосіб зробити це - змінити сценарій, щоб він також визначав команду для скасування ефекту сценарію:

export linuxmachine01="sdb sdc sdf sdd sde sdg"
export linuxmachine02="sde sdd sdb sdf sdc"
export linuxmachine03="sdb sdd sdc sde sdf"
export linuxmachine06="sdb sde sdf sdd"
alias linuxmachines_mount_point='for v in linuxmachine01 linuxmachine02 linuxmachine03 linuxmachine04; do unset $v; done; unalias linuxmachines_mount_point'

Чому псевдонім, а не функція? Зауважте, що псевдоніми вимкнено в неінтерактивних оболонках за замовчуванням, тому поза скринькою це не працюватиме в сценарії.
Чарльз Даффі

... насправді це було б ще простіше, якби ми визначили лише одну змінну, і, таким чином, потрібно було скинути лише одну:, declare -A linuxmachines=( [01]="sdb sdc sdf" [02]="sde sdd sdb" [03]="whatever" )тоді це просто unset linuxmachinesповернути.
Чарльз Даффі

@CharlesDuffy: і псевдонім, і функція відмінно підходять для цієї мети. Причина, по якій я не пропоную вкладати все в одну змінну, полягає в тому, що визначення команди скасувати набагато більш загальне. Ви можете визначити не лише змінні, але й функції, псевдоніми, системні налаштування, налаштування терміналу тощо. Це забезпечує кращу абстракцію, оскільки вам не потрібно дбати про точний зміст команди скасувати.
Лежи Райан

Я вважаю, що моя суть вище полягає в тому, що псевдоніми не відповідають цілям, якщо "мета" включає неінтерактивне використання (тобто виклик із сценаріїв).
Чарльз Даффі

0

Ви можете написати свій linuxmachines_mount_point.txt так

test "$linuxmachine01" && unset -v linuxmachine01 || linuxmachine01="sdb sdc sdf sdd sde sdg"

Коли вам потрібні ваші змінні

source linuxmachines_mount_point.txt

Коли ви хочете видалити змінні

source linuxmachines_mount_point.txt

0

Якщо ви використовуєте sourceкоманду для активації a VirtualEnvironment, ви можете вийти з неї за допомогою команди deactivate.

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