如何将多行输入从标准输入读取到变量中以及如何在 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

tee 完成工作

#!/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 的其余部分:

  • 环境 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%|||}"
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top