Как выполнить вывод команды в текущей оболочке?


Я хорошо осведомлен о source (Он же .) утилита, которая будет принимать содержимое из файла и выполнять их в текущей оболочке.

теперь я преобразую некоторый текст в команды оболочки, а затем запускаю их следующим образом:

$ ls | sed ... | sh

ls это просто случайный пример, исходный текст может быть любым. sed тоже, просто пример для преобразования текста. Интересный бит-это sh. Я трубу все, что я получил sh и он работает оно.

моя проблема в том, что это означает запуск новой суб оболочки. Я бы предпочел, чтобы команды выполнялись в моей текущей оболочке. Как я мог бы сделать с source some-file, если бы у меня были команды в текстовый файл.

Я не хочу создавать временный файл, потому что чувствует себя грязным.

кроме того, я хотел бы начать свою суб-оболочку с теми же характеристиками, что и моя текущая оболочка.

обновление

ОК, решения, использующие backtick конечно работа, но мне часто нужно делать это, пока я проверяю и изменяю вывод, поэтому я бы предпочел, чтобы в конце концов был способ передать результат во что-то.

грустно обновления

а,/dev/stdin это выглядело так красиво, но, в более сложном случае, это не сработало.

Итак, у меня есть это:

find . -type f -iname '*.doc' | ack -v '.doc$' | perl -pe 's/^((.*).doc)$/git mv -f  .doc/i' | source /dev/stdin

которая гарантирует все .doc файлы имеют расширение в нижнем регистре.

и с которым кстати, можно справиться xargs, но это к делу не относится.

find . -type f -iname '*.doc' | ack -v '.doc$' | perl -pe 's/^((.*).doc)$/ .doc/i' | xargs -L1 git mv

Итак, когда я запускаю первый, он сразу же выйдет, ничего не происходит.

9 70

9 ответов:

$ ls | sed ... | source /dev/stdin

обновление: это работает в bash 4.0, а также tcsh и dash (если вы измените source to .). По-видимому, это было багги в bash 3.2. Из bash 4.0 примечания к выпуску:

Исправлена ошибка, приводившая `.'не читать и не выполнять команды из нерегулярных файлов, таких как устройства или именованные каналы.

The eval команда существует именно для этой цели.

eval "$( ls | sed... )"

больше bash manual:

eval

          eval [arguments]

аргументы объединены вместе в единую команду, которая затем читается и выполняется, и его статус выхода возвращается как выход статус eval. Если нет аргументы или только пустые аргументы, статус возврата равен нулю.

Ничего себе, Я знаю, что это старый вопрос, но я нашел себя с той же самой проблемой в последнее время (вот как я попал сюда).

в любом случае - мне не нравится source /dev/stdin ответ,но я думаю, что нашел лучший. Это обманчиво просто на самом деле:

echo ls -la | xargs xargs

приятно, правда? На самом деле, это все еще не делает то, что вы хотите, потому что если у вас есть несколько строк, он объединит их в одну команду вместо того, чтобы запускать каждую команду отдельно. Так что решение я нашел это:

ls | ... | xargs -L 1 xargs

the -L 1 опция означает, что вы используете (не более) 1 строку на выполнение команды. Примечание: если ваша строка заканчивается конечным пробелом, она будет объединена со следующей строкой! Поэтому убедитесь, что каждая строка заканчивается не пробелом.

наконец, вы можете сделать

ls | ... | xargs -L 1 xargs -t

чтобы увидеть, какие команды выполняются (-Т многословен).

надеюсь, что кто-то читает это!

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

source <(echo id)

Я считаю, что это "правильный ответ" на вопрос:

ls | sed ... | while read line; do $line; done

то есть, можно трубить в while loop; the read команда команда берет одну строку из его stdin и присваивает его переменной $line. $line затем становится командой, выполняемой в цикле; и она продолжается до тех пор, пока на ее входе не будет больше строк.

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

`ls | sed ...`

Я вроде как чувствую себя ls | sed ... | source - было бы красивее, но, к сожалению,source не понимаю - означает stdin.

Я думаю, что ваше решение-это замена команды с помощью обратных кавычек:http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html

см. раздел 3.4.5

почему бы не использовать source потом?

$ ls | sed ... > out.sh ; source out.sh

чтобы использовать решение mark4o на bash 3.2 (macos) здесь строка может использоваться вместо конвейеров, как в этом примере:

. /dev/stdin <<< "$(grep '^alias' ~/.profile)"