72

我想要做的是以下内容:

  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
4

7 回答 7

79

这对我有用:

myvar=`cat`

echo "$myvar"

周围的报价$myvar很重要。

于 2008-10-17T17:04:24.917 回答
31

在 Bash 中,有另一种方法;man bash提到:

命令替换$(cat file)可以替换为等效但更快的$(< file).

$ myVar=$(</dev/stdin)
hello
this is test
$ echo "$myVar"
hello
this is test
于 2013-03-07T10:47:31.880 回答
12

三通做的工作

#!/bin/bash
myVar=$(tee)
于 2014-02-27T09:33:47.297 回答
11

[更新]

如果管道中没有任何内容,则此分配将无限期挂起...

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

我们可以通过read对第一个字符进行超时来防止这种情况。如果超时,返回码将大于 128,我们将知道 STDIN 管道(又名/dev/stdin)是空的。

否则,我们通过...获得 STDIN 的其余部分

  • 仅为命令设置IFS为 NULLread
  • 关闭转义-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%|||}"
于 2017-11-17T04:36:06.660 回答
7

是的,它也适用于我。谢谢。

myvar=`cat`

是相同的

myvar=`cat /dev/stdin`

嗯,是。从bash手册页:

将字符括在双引号中会保留引号内所有字符的字面值,但 $、`、\ 以及启用历史扩展时的! 除外。字符 $ 和 ` 在双引号中保留其特殊含义。

于 2008-10-17T17:12:44.870 回答
7

如果您确实关心在输出末尾保留尾随换行符,请使用以下命令:

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

这使用了这里的技巧。

于 2014-09-09T07:01:01.323 回答
2

读取也可以使用设置选项 -d [DELIMITER],其中 `input' DELIMITER 是一个字符长。如果您设置-read d '',则它会读取到 null 或所有输入。

请记住,无论如何,Bash 不能在变量中保存空字节。

read -d'' myvar
echo "$myvar"

Obs:虽然不保留尾随换行字节..

于 2021-09-14T20:21:14.903 回答