У меня есть команда, хранящаяся в переменной. Давайте представим, что переменная $i
имеет значение:
cat -nT index.php |grep 'someregex'
Когда я пытаюсь выполнить указанную выше переменную, набирая $i
ее, происходит сбой, потому что оболочка пытается выполнить всю переменную как одну команду. Я также пытался использовать eval($i)
и вставлять $i
галочки.
Как сделать так, чтобы оболочка выполнялась, $i
как если бы это была команда? И почему это не работает так же, как.
$i='echo hi'; $i
Это из-за того, что мне пришлось взламывать одинарные кавычки? (Потому что вы не можете их вложить.) В настоящее время мое решение
echo $i > /foo; . /foo
Но я не хочу создавать файл только для этого, только чтобы удалить его позже.
Что я имею в виду под "я взломал в одиночных кавычках, я сделал:
$i='cat index.php | grep -P '"'"'MYREGEXHERE'"'"
Ответы:
Краткий ответ: см. BashAQ # 50: я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу! ,
Длинный ответ: это из-за порядка, в котором bash анализирует командную строку. В частности, он ищет такие вещи, как каналы и перенаправления, прежде чем он расширяет значения переменных, и не возвращается и не просматривает каналы и т. Д. В расширенных значениях. По сути, переменные подставляются примерно в середине процесса синтаксического анализа, поэтому перед выполнением значение анализируется только наполовину.
Чтобы решить эту проблему, вам нужно ответить на вопрос @ slhck: почему команда хранится в переменной в первую очередь? Какую реальную проблему вы пытаетесь решить? В зависимости от конкретной цели, существует ряд возможных решений:
Не храните его в переменной, просто выполняйте его напрямую. Хранить команды для последующего использования сложно, а если вам не нужно, просто не делайте этого.
Используйте функцию вместо переменной. Вот для чего они, в конце концов:
Основным недостатком этого является то, что вы не можете создавать функцию динамически - вы не можете условно включать или исключать код из функции (хотя сама функция может иметь условные элементы, которые выбираются при ее выполнении).
Использование
eval
. Это следует считать последним средством, поскольку легко получить неожиданное поведение. По сути, он запускает команду через еще один полный этап синтаксического анализа, поэтому все каналы и т. Д. Получают свое полное значение, но это также означает, что части команды, которые вы считали просто данными, также будут проанализированы и, возможно, выполнены. Имена файлов, содержащие метасимволы оболочки (труба, точка с запятой, кавычка / апостроф и т. Д.), Могут иметь странные и иногда опасные последствия. Если вы используетеeval
, по крайней мере, заключите в кавычки строку, в противном случае ее содержимое, по сути, будет проанализировано полтора раза, с еще более странными результатами.РЕДАКТИРОВАТЬ: Другой стандартный подход хранилища-команда-в-переменной заключается в использовании массива вместо простой переменной. Это позволяет без проблем хранить команды со сложными аргументами (например, содержащими пробелы), но не будет хранить такие вещи, как каналы и перенаправления. Таким образом, подход массива не будет полезен в этом конкретном случае.
источник
eval
метод. Это помешало мне задать тот же вопрос :). У меня что-то подобноеsudo rsync -aAHXi -n --delete-excluded --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/lost+found","/mnt/DATA/*","/var/log/*","/var/swap","/var/cache/apt/archives/*.deb"} -e ssh root@piac_wireless:/ /home/mrx/Docs/RPi/backup/piac/piac_usb-root
не выполнялось исключения правильно.eval
для этого - слишком много способов ошибиться. Массив был бы лучшим способом сделать это. Смотрите здесь , здесь и здесь для примеров.Это должно просто работать:
Остерегайтесь, что
eval
представляет потенциальные уязвимости и неожиданные ситуации поведения, поэтому должны использоваться, если вообще, с особой осторожностью.источник
eval
, вам действительно нужно использовать двойные кавычки (eval "$i"
), чтобы избежать очень-очень-странных эффектов. Например, попробуйте это с помощьюa="cat -nT index.php |grep ' .* '"
(то есть регулярное выражение должно соответствовать двум пробелам с любой последовательностью символов между ними) и посмотрите, что на самом деле происходит. Для дополнительного кредита объясните, почему это происходит.При объявлении переменной не следует использовать знак доллара в качестве префикса.
Попробуй это:
источник