Я пытаюсь сохранить вывод из трубы в переменную.

После прочтения этого поста (доступа к выводу канала Bash с помощью «read») у меня возникли некоторые сомнения, вспомнив, удастся ли мне когда-либо добиться этого в системе Unix.

Затем я обнаружил этот пост (« Как перебрать имена файлов, возвращаемых функцией find?»), И мне напомнили, что он работает, иногда используя read -r <varname> .

Среда:

User@Computer /cygdrive/...
$ echo $SHELL
/bin/bash

User@Computer /cygdrive/...
$ echo $BASH_VERSION
4.4.5(1)-release

User@Computer /cygdrive/...
$ uname -a
CYGWIN_NT-10.0 Computer 2.6.1(0.305/5/3) 2016-12-16 11:55 x86_64 

User@Computer /cygdrive/...
$ read --help
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
    Read a line from the standard input and split it into fields.

Попытки:

User@Computer /cygdrive/...
$ echo $var


User@Computer /cygdrive/...
$ echo "hi" | read var

User@Computer /cygdrive/...
$ echo $var


User@Computer /cygdrive/...
$ echo "hi" | read -r var

User@Computer /cygdrive/...
$ echo $var

User@Computer /cygdrive/...
$ read var
hi

User@Computer /cygdrive/...
$ echo $var
hi

User@Computer /cygdrive/...
$ echo "hi" | cat
hi

User@Computer /cygdrive/...
$ echo -e '1\n2\n3\n' | xargs
1 2 3

Я также попробовал это в собственном процессе и окне bash.exe :

User@Computer /cygdrive/...
$ echo "hi" | read var;echo $var;

То же самое делается в "Bash на Ubuntu в Windows" bash.exe:

echo "hi" | read var;echo $var;

До сих пор нет успешного результата задания. Я знаю, что могу обойти этот метод, вместо этого, вероятно, используя $() или стрелки перенаправления.

Есть ли способ сделать это с помощью этого метода командной строки read в Windows?

Обновить

На некоторые ответы я знал, что некоторые будут публиковать альтернативы, такие как $() . Вот почему я намеренно уже упомянул этот метод, включая ссылку, где несколько из них уже были перечислены, а также специально спросил, есть ли способ использовать утилиту read строки для хранения ввода в переменную, не используя перенаправление, а вместо этого передавая данные через цепочка команд, как я делал раньше в других системах, но на этот раз в Windows.

3 ответа3

0

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

Пример:

sharuzzaman@laptop /cygdrive/...
$ mkfifo mypipe

sharuzzaman@laptop /cygdrive/...
$ echo "hi" > mypipe &
[1] 5260

sharuzzaman@laptop /cygdrive/...
$ read asdf < mypipe

sharuzzaman@laptop /cygdrive/...
$ echo $asdf
hi
[1]+  Done                    echo "hi" > mypipe
0

На другие ответы они кажутся изящными подходами с некоторыми хорошими примерами, но мне было действительно любопытно, почему этот подход, который я использовал ad-hoc и в некоторых сценариях оболочки, «перестал работать» или не работал на моей Windows система.

Я не видел, чтобы они опубликовали какие-либо ответы, непосредственно касающиеся того, как я могу сделать это с помощью read и каналов, так что вот мое обновление как форма закрытия, где я тестирую некоторые примеры и выделяю конкретные функциональные возможности, на которые ссылались.

Что ж, к комментариям по этому вопросу я могу показать, что это работает на моем компьютере Mac (10.12.5), в iTerm 3.0.15, в оболочке fish :

⋊> ~ echo "hi" | read var;echo $var;
hi
⋊> ~ fish -v
fish, version 2.6.0

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

Затем я снова попробовал подход на моем Mac в обоих переводчиках.

В fish:

⋊> ~ echo -ne '1\n2\n3\n' | while read line; echo "a$line""a"; end
a1a
a2a
a3a

В bash:

bash-3.2$ echo -ne '1\n2\n3\n' | while read line; do echo "a$line""a"; done
a1a
a2a
a3a

bash-3.2$ echo $BASH
/bin/bash
bash-3.2$ echo $BASH_VERSION
3.2.57(1)-release

Кажется, что все функциональные возможности (в основном) работают, как и ожидалось. Я был немного удивлен, обнаружив, что переменная не выводится в bash , но моя первоначальная проблема заключалась в том, что я не получил ожидаемые данные для сохранения в этом цикле. Мне придется еще раз проверить мой код, помня обо всем этом.

Конечный результат

Основной момент, который будет выделен здесь, состоит в том, чтобы не хранить стандартный ввод в простые переменные путем конвейерной передачи в bash и продолжать в обычном режиме в сценарии, как это выполняется в подоболочке, согласно Sharuzzaman Ahmat Raslan и dave_thompson_085.

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

Другие заметки

Я думаю, что еще одна проблема в одной из моих строк кода заключалась в том, что я пытался использовать read -r <varname> , но вместо этого read -p <varname> . Последний использует дополнительный аргумент, чтобы сформировать приглашение для команды чтения, и в моем примере только с 1 аргументом не оставляет полезного имени переменной для хранения информации и извлечения из нее. Первый иногда полезен в примерах других, когда не хочет использовать escape-последовательности возврата, когда бы это ни было. Так что избегайте опечаток, как этот!

0

Для однострочных результатов канонический способ сделать это в bash:

variable=$(the_command the_command_args)

например:

today=$(date +%Y%m%d) 

(и аргументы команды могут содержать переменные $ при необходимости).

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

for f in $(ls -1)
do
    echo @@@@"$f"
done

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .