Как прочитать мутлиновый ввод из stdin в переменную и как распечатать его в оболочке (sh, bash)? - PullRequest
53 голосов
/ 17 октября 2008

Я хочу сделать следующее:

  1. чтение из многострочного ввода из stdin в переменную A
  2. совершать различные операции на A
  3. труба A без потери символов-разделителей (\n, \r, \t и т. Д.) Для другой команды

В настоящее время проблема в том, что я не могу прочитать это командой read, потому что она останавливает чтение на новой строке.

Я могу читать стандартный ввод с помощью cat, например:

my_var=`cat /dev/stdin`

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

Мой пример скрипта выглядит так:

#!/usr/local/bin/bash

A=`cat /dev/stdin`

if [ ${#A} -eq 0 ]; then
        exit 0
else
        cat ${A} | /usr/local/sbin/nextcommand
fi

Ответы [ 6 ]

60 голосов
/ 17 октября 2008

Это работает для меня:

myvar=`cat`

echo "$myvar"

Кавычки вокруг $myvar важны.

22 голосов
/ 07 марта 2013

В Bash есть альтернативный способ; man bash упоминает:

Команда подстановки $(cat file) может быть заменена эквивалентной, но более быстрой $(< file).

$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test
7 голосов
/ 27 февраля 2014

тройник делает работу

#!/bin/bash
myVar=$(tee)
7 голосов
/ 17 октября 2008

Да, это работает и для меня. Спасибо.

myvar=`cat`

совпадает с

myvar=`cat /dev/stdin`

Ну да. Со страницы руководства bash:

Заключение символов в двойные кавычки сохраняет буквальную ценность всех символы в кавычках, за исключением $, `, \, и, когда расширение истории включен,! Символы $ и ` сохранить их особое значение в двойных кавычках.

4 голосов
/ 09 сентября 2014

Если вы заботитесь о сохранении конечных строк в конце вывода, используйте это:

myVar=$(cat; echo x)
myVar=${myVar%x}
printf %s "$myVar"

Здесь используется трюк из здесь .

2 голосов
/ 17 ноября 2017

[обновлено]

Это задание будет висеть бесконечно, если в трубе ничего нет ...

var="$(< /dev/stdin)"

Мы можем предотвратить это, сделав тайм-аут read для первого символа. Если время ожидания истекло, код возврата будет больше 128, и мы будем знать, что канал STDIN (a.k.a /dev/stdin) пуст.

В противном случае мы получим остаток STDIN ...

  • установка IFS в NULL только для команды read
  • отключение выходов с помощью -r
  • устранение разделителя чтения с помощью -d ''.
  • и, наконец, добавив, что к персонажу мы получили изначально

Таким образом ...

__=""
_stdin=""

read -N1 -t1 __  && {
  (( $? <= 128 ))  && {
    IFS= read -rd '' _stdin
    _stdin="$__$_stdin"
  }
}

В этом методе не используется var="$(command ...)" Подстановка команд, которая, по замыслу, всегда удаляет любые завершающие символы новой строки.

Если предпочтительна подстановка команд, чтобы сохранить завершающие символы новой строки, мы можем добавить один или несколько символов-разделителей к выводу внутри $(), а затем удалить их снаружи.

Например (примечание $(parens) в первой команде и ${braces} во второй) ...

_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...