Коротка відповідь: див. BashAQ # 50: Я намагаюся поставити команду в змінну, але складні випадки завжди не вдається! .
Довга відповідь: це через порядок, в якому bash аналізує командний рядок. Зокрема, він шукає такі речі, як труби та переадресації, перш ніж розширювати змінні значення, і не повертається назад і не шукає труби тощо в розширених значеннях. По суті, змінні замінюються приблизно на півдорозі процесу розбору, тому значення отримується лише на півдорозі, перш ніж його виконати.
Для того, щоб вирішити це, вам потрібно відповісти на питання @ slhck: чому команда зберігається в змінній в першу чергу? Яку актуальну проблему ви намагаєтеся вирішити? Залежно від реальної мети, існує ряд можливих рішень:
Не зберігайте його у змінній, просто виконайте її безпосередньо. Зберігання команд для подальшого використання є складним, і якщо вам це не потрібно, просто не потрібно.
Використовуйте функцію замість змінної. Зрештою, для чого вони:
i() { cat -nT index.php |grep 'someregex'; }
i
Основним недоліком цього є те, що ви не можете динамічно створювати функцію - ви не можете умовно включати або виключати код з функції (хоча сама функція може мати умовні елементи, вибрані під час її виконання).
Використовуйте eval
. Це слід вважати крайнім заходом, оскільки легко отримати несподівану поведінку. Він по суті запускає команду через інший повний прохід для розбору, тому всі труби тощо отримують повний сенс - але це також означає, що частини команди, які ви вважали лише даними, також будуть проаналізовані та, можливо, виконані. Імена файлів, що містять метахарактеристики оболонок («труба», крапка з комою, цитата / апостроф тощо), можуть мати дивні, а іноді й небезпечні наслідки. Якщо ви користуєтесь eval
, принаймні двічі цитуйте рядок, інакше його вміст, по суті, проаналізується в півтора рази, з ще більш дивними результатами.
i="cat -nT index.php |grep 'someregex'"
eval "$i"
EDIT: Ще один стандартний підхід store-a-command-in-a-змінний - використовувати масив замість простої змінної. Це дозволяє без проблем зберігати команду зі складними аргументами (наприклад, що містять пробіли), але не зберігатиме такі речі, як труби та переадресації. Отже, підхід до масиву не буде корисним у цьому конкретному випадку.