Вывод на переменную с помощью косвенной команды (eval)

Что не так с этой косвенной командой при запуске с eval?

#!/bin/bash OS=AIX host=myhost CMD_AIX="(o=\`host \"$host\" \`)" CMD=\$CMD_$OS echo $CMD eval echo $CMD eval "$CMD" 

Ouput:

 $ myscript.sh $CMD_AIX (o=`host "myhost" `) myscript.sh: line 12: (o=`host: command not found 

EDIT – ПРИМЕЧАНИЯ: он находится в очень гетерогенной структуре с примерно 40 серверами, смешивая SCO, AIX и Linux, несколько версий каждого, включая варианты 32 и 64 бит. SCO и AIX не могут быть обновлены. Оболочка Bash и Korn распространена на всех серверах, но я ограничена версией 3 bash (в SCO), Ksh имеет несколько различий между ними, поэтому мы предпочитаем bash, которые не поддерживают ассоциативные массивы в v3 (это не могут быть обновлены, и это вне моих решений, и эти серверы будут заменены на AIX 7 и Linux через несколько месяцев).

Есть большая система для поддержки, которая включает в себя некоторые скрипты, уже основанные на sh и bsh, мы не будем и не можем ее восстановить сейчас, просто поддерживаем обслуживание, чтобы противостоять некоторым месяцам до конца замены.

Подход, используемый в этих сценариях, в значительной степени распространен в большом решении, которое генерирует некоторые скрипты, которые мы не можем изменить с нуля.

Пример кода выше – это всего лишь принятый фрагмент, это не настоящий код. Пожалуйста, не рассматривайте логику, просто проблему косвенности (eval).

РЕШЕНИЕ: У меня есть решение, которое отлично работает, просто цепляя eval , например:

 torun=`eval $CMD` output=`eval torun` 

Этот ответ и еще один , который работал очень хорошо и отвечал на вопрос, были странно проголосовали много.

5 Solutions collect form web for “Вывод на переменную с помощью косвенной команды (eval)”

Таким образом, у вас есть переменная CMD , значением которой является строка $CMD_AIX , а значение переменной CMD_AIX – это строка (o=`host "myhost" `) . Вы хотите интерпретировать значение CMD_AIX в качестве команды оболочки и выполнить ее.

Чтобы выполнить значение CMD_AIX в качестве команды оболочки, вам нужно создать команду оболочки, которая делает это. Вот что такое eval для:

 eval "$CMD_AIX" 

Эта команда, в свою очередь, построена динамически. Поэтому вам нужно запустить его с помощью eval :

 dispatcher=… eval "$dispatcher" 

Учитывая способ построения внутренней команды, мы получаем

 dispatcher="eval \"\$CMD_$OS\"" eval "$dispatcher" 

Или вырезать одну переменную:

 eval "eval \"\$CMD_$OS\"" 

Обратите внимание, что команда (o=`host "myhost" `) бессмысленна: она назначает вывод host переменной o в подоболочке; значение не предоставляется вне подоболочки. Удалите круглые скобки. Кроме того, host \"$host\" является странным: вы помещаете значение переменной host между двойными кавычками; это не имеет значения, поскольку имена хостов не содержат специальных символов оболочки, но для использования значения переменной при оценке фрагмента оболочки вы должны оставить нерасширенный здесь узел.

 #!/bin/sh OS=AIX # should probably be OS=`uname -r` host=myhost CMD_AIX="o=\`host \"\$host\"\`" eval "eval \"\$CMD_$OS\"" 

Если у вас есть ksh93 или bash ≥ 4.0, вы можете упростить этот скрипт, используя ассоциативные массивы. Вместо того, чтобы набивать код для каждой операционной системы в другую переменную, поместите их в ассоциативный массив .

 #!/usr/bin/env bash typeset -A commands commands[AIX]="o=\`host \"\$host\"\`" OS=AIX host=myhost if [ -n "${commands[$OS]}" ]; then eval "${commands[$OS]}" else echo >&2 "Operating system $OS not supported" exit 2 fi 

Я думаю, что проблема с тем, что вы там делаете, заключается в том, что это не имеет никакого смысла. Не обижайтесь, но я имею в виду, что я думаю, что у вас есть неправильное представление о том, что делает eval . Похоже, вы пытаетесь использовать его только для запуска команды – это базовая функциональность оболочки и не требует, чтобы оболочка пыталась интерпретировать свои последние расширения как новые команды – это то, что делает eval .

В любом случае, как у вас есть все ваши цитаты, написанные вами, вы защищаете что-либо от второй оценки. Или, скорее, вы полностью защищаете первый проход – и поэтому ничего не происходит до второго прохода. Проблема заключается в том, что вы можете просто не выполнять вторую оценку (и второй уровень кавычек) вообще.

Мне кажется, что вы пытаетесь запустить определенную команду на основе значения $OSможет быть …? Ну, это одна из самых доступных функций API в оболочке.

Например:

 OS=AIX host=myhost _cmd_AIX() { host "$host"; } _cmd_WIN() { exit "$((LOSE=1))"; } 

Вы видите – вы можете запускать указанные определенные функции. Их имя команды не нуждается в каком-либо специальном втором интерпретаторе, чтобы иметь значение – даже когда это происходит в результате расширения. Он просто должен находиться в командном положении. Они все равно даже будут принимать параметры таким образом – так что вы могли бы передать $host как $1 если хотите. Вы просто называете это следующим образом:

 "_cmd_$OS" 

$OS var будет расширяться до AIX и полученное командное слово будет _cmd_AIX – это предопределенная функция оболочки, имя которой происходит в целом и правильно разграниченное слово оболочки в командном положении – и поэтому оно выполняется. Просто так. Никаких искажений не требуется – и он даже поставляется с собственным массивом.

Переопределить $OS в любое время на имя какого-либо другого действительного суффикса для других видов поведения.

С zsh :

 $ echo $CMD $CMD_AIX $ echo ${(e)CMD} (o=`host "myhost" `) $ echo ${(e)${(e)CMD}} (o=myhost has address 1.2.3.4) 

Флаг расширения (e) – это вычисление разложений в значении расширяемой переменной.

С ksh93:

 $ function CMD.get { eval ".sh.value=\"$_\""; } $ function CMD_AIX.get { eval ".sh.value=\"$_\""; } $ echo "$CMD_AIX" (o=myhost has address 1.2.3.4) $ echo "$CMD" (o=myhost has address 1.2.3.4) $ CMD=\$USER $ echo "$CMD" stephane 

CMD.get – это функция дисциплины, которая вызывается в любое время, когда расширяется $CMD обычно используется для определения того, что должно быть для этого расширения, чтобы позволить переменным с динамическим контентом. Здесь мы определяем его как возвращающий оценку его содержимого в двойных кавычках (который предполагает, что значение не содержит двойных кавычек).

Вы также можете использовать типы:

 typeset -T evaluating_variable=( function get { eval ".sh.value=\"$_\""; } ) OS=AIX host=myhost evaluating_variable CMD_AIX='(o=`host "'$host'"`)' evaluating_variable CMD=\$CMD_$OS 

Теперь, почему вы хотите сделать это в сценарии оболочки, другое дело.

eval eval $CMD вместо последней строки исправляет проблему

Это фиксировало проблему:

 eval `eval echo $CMD` 

вместо:

 eval "$CMD" 
  • Как создать несколько файлов tar с помощью сценария bash и использовать дату в качестве имен файлов?
  • Замените все символы новой строки на пространство, за исключением последнего
  • Скрипт для эмуляции Windows + клавиша
  • difficalty для сохранения вывода traceroute в переменной оболочки?
  • Условия внутреннего контура должны зависеть от хода внешнего цикла
  • Else not Executing
  • Печатать аргументы оболочки в обратном порядке
  • Как конвертировать uA / mA в uA в каждой строке csv-файла с помощью c-оболочки?
  • Правильное литье типов в сценарии оболочки для использования с циклом while и модулем
  • Почему этот плагин Bash NRPE не возвращает переменную Nagios?
  • Доступ к Google-трансляции через wget
  • Interesting Posts

    Эквивалент функции «copy = 2» ZFS в Linux с LVM

    Команда ps не найдена в CentOS

    Просмотр файлов из зеркального RAID вне устройства

    Asterisk и NAT: регистрация SIP и IAX не удалась при удаленном соединении за NAT

    Сортировка STDIN по длине и количеству небилетов в скрипте Bash

    OpenWRT: Как создать интерфейс для виртуальных PPP-интерфейсов pptpd?

    ls recursive on home dir только без флагов, отличных от цвета

    xrandr scale 2×2 для мультидисплея (4K HiDPI и Full HD mix) – размытый вывод

    Что означает статус «активный (выходящий)» для (пользовательского) сервиса?

    Подходы, чтобы запретить пользователю удалять домашнюю папку

    Как сделать dd сбой, если указано недопустимое значение пропуска?

    Могу ли я перенести файл в папку (на удаленном сервере), доступную для записи только через root (через sudo)?

    Как запустить команды Emacs nnrss- *

    Применение функции bash для каждого файла в подпапке рекурсивно

    Как изменить Toolkit в Linux Mint для GTK

    Linux и Unix - лучшая ОС в мире.