задайте переменную внутри heredoc и используйте их снаружи

Я пытаюсь установить переменную «count» во время выполнения команды внутри heredoc вместе с таймаутом, но я не могу получить переменную «count» вне heredoc.

Как я могу это достичь?

  • Мой сценарий более сложный, но я думал, что получить ответ для этого будет достаточно.

    timeout 10 bash << EOC count=$(ls -l /tmp/ | wc -l) EOC echo "count: $count" 

3 Solutions collect form web for “задайте переменную внутри heredoc и используйте их снаружи”

Вы не можете. Переменные, назначенные в под-оболочке, не влияют на родительскую оболочку.

Сделайте это вместо этого:

 count=$(timeout 10 ls -l /tmp/ | wc -l) echo "count: $count" 

Я не думаю, что вы можете это достичь. Большая проблема заключается в том, что у вас есть процесс bash оценивающий конвейер, а затем сохраняя значение этого конвейера в count переменных оболочки. timeout сам по себе не является оболочкой, встроенной в мой ноутбук Arch, поэтому есть третий уровень процесса. Поскольку timeout выдает команду, на которую он ждет, есть третий уровень процесса.

Это shell-that-invokes-timeout -> timeout -> bash-invoked-by-timeout -> value-of- count

Мне кажется, что вам нужно перестроить сценарий оболочки, чтобы иметь возможность использовать значение count (или то, что вы хотите выполнить).

Если вам действительно нужен timeout в команде, вы должны, вероятно, отправить вывод команды в файл, а затем прочитать этот файл:

 if timeout ls -l /tmp > /tmp/some.well.known.name then VAR=$(wc -l /tmp/some.well.known.name) else : handle timeout fi 

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

Использование здесь-документа вместо bash -c не изменяет этот факт. Ваш пример эквивалентен timeout 10 bash -c "count=$(ls -l /tmp/ | wc -l)" . (Кстати, это запускает ls -l /tmp/ | wc -l во внешней оболочке, а не в случае bash который вы порождаете: если вы хотите сделать эквивалент timeout 10 bash -c "count=$(ls -l /tmp/ | wc -l)" , вам нужно использовать <<\EOF или <<'EOF' или тому подобное.)

Если вам нужно только получить значение одной переменной, вы можете использовать подстановку команд:

 count=$(timeout 10 bash -c '…') 

Если вам нужно задать множество переменных или массив, вам нужно будет сделать некоторую кодировку и декодирование. Вы можете получить bash, чтобы сделать это для вас: declare -p foo bar печатает способ определения foo и bar который правильно указан для вызывающей оболочки.

 eval "$(bash -c '…; declare foo bar')" 

Обратите внимание, что это объявляет переменные локально, поэтому, если вы запустите его в функции, переменные не будут доступны, когда функция вернется. Если вам нужны переменные, которые будут доступны при возврате, вам нужно снова назначить их с declare -g ; это работает только для скаляров:

 f () { eval "$(bash -c '…; declare foo bar')" declare -g foo="$foo" bar="$bar" } 

В качестве альтернативы, если вы знаете, что значения переменных не могут содержать новые строки, strip declare -… с начала каждой строки на выходе declare -p .

  • Повторное использование выхода grep
  • Переменная, случайным образом выбранная из трех чисел (10, 100 и 1000)
  • Как определяется статус возврата переменной назначения?
  • BASH: использование awk для фильтрации уникальных строк приводит к 0 массиву длины
  • Переменные доступа, установленные внутри подстановок
  • Вырезать имя файла и результат поиска grep из пути
  • Извлечение второго слова из строковой переменной
  • Имя переменной BASH, содержащее номер номер
  • Ссылка на составную переменную Ksh
  • Переменная, связанная с переменной
  • как понять выход «echo $ -»?
  • Linux и Unix - лучшая ОС в мире.