Как прочитать множественный ввод из stdin в переменную и как распечатать его в shell (sh, bash)?

StackOverflow https://stackoverflow.com/questions/212965

  •  03-07-2019
  •  | 
  •  

Вопрос

То, что я хочу сделать, это следующее:

  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
Это было полезно?

Решение

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

myvar=`cat`

echo "$myvar"

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

Другие советы

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

  

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

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

тройник выполняет свою работу

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

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

myvar=`cat`

совпадает с

myvar=`cat /dev/stdin`

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

  

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

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

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

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

[обновлено]

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

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

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

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

  • настройка IFS обнулить только для 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%|||}"
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top