Подтвердить что ты не робот

Как прочитать вход mutliline из stdin в переменную и как распечатать его в оболочке (sh, bash)?

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

  • читайте в нескольких строках ввода stdin в переменную A
  • выполнять различные операции с A
  • pipe A без потери символов разделителя (\n, \r, \t и т.д.) к другой команде

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

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

my_var=`cat /dev/stdin`

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

Мой пример script выглядит следующим образом:

#!/usr/local/bin/bash

A=`cat /dev/stdin`

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

Ответ 1

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

myvar=`cat`

echo "$myvar"

Важны цитаты вокруг $myvar.

Ответ 2

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

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

$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test

Ответ 3

tee выполняет работу

#!/bin/bash
myVar=$(tee)

Ответ 4

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

myvar=`cat`

совпадает с

myvar=`cat /dev/stdin`

Ну да. На странице bash man:

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

Ответ 5

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

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

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

Ответ 6

[обновлено]

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

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 ...)" Command Substitution, которая, по своему усмотрению, всегда будет удалять любые завершающие символы новой строки.

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

Например (обратите внимание $(parens) на первую команду и ${braces} на секунду)...

_stdin="$(awk '{print}; END {print "|||"}' /dev/stdin)"
_stdin="${_stdin%|||}"