如何将标准输入中的多行输入读入变量以及如何在 shell(sh,bash) 中打印出来?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/212965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:45:20  来源:igfitidea点击:

How to read mutliline input from stdin into variable and how to print one out in shell(sh,bash)?

bashshellstdinmultiline

提问by Tanktalus

What I want to do is the following:

我想要做的是以下内容:

  1. read in multiple line input from stdininto variable A
  2. make various operations on A
  3. pipe Awithout losing delimiter symbols (\n,\r,\t,etc) to another command
  1. 读入多行输入stdin到变量中A
  2. 进行各种操作 A
  3. A,而不会失去定界符符号(\n\r\t等)到另一个命令

The current problem is that, I can't read it in with readcommand, because it stops reading at newline.

当前的问题是,我无法使用read命令读取它,因为它在换行符处停止读取。

I can read stdin with cat, like this:

我可以用 读取标准输入cat,如下所示:

my_var=`cat /dev/stdin`

, but then I don't know how to print it. So that the newline, tab, and other delimiters are still there.

,但后来我不知道如何打印它。这样换行符、制表符和其他分隔符仍然存在。

My sample script looks like this:

我的示例脚本如下所示:

#!/usr/local/bin/bash

A=`cat /dev/stdin`

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

回答by Tanktalus

This is working for me:

这对我有用:

myvar=`cat`

echo "$myvar"

The quotes around $myvarare important.

周围的引号$myvar很重要。

回答by Ingo Karkat

In Bash, there's an alternative way; man bashmentions:

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

The command substitution $(cat file)can be replaced by the equivalent but faster $(< file).

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

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

回答by Sergey Grigoriev

teedoes the job

t 恤做的工作

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

回答by DocSalvager

[updated]

[更新]

This assignment will hang indefinitely if there is nothing in the pipe...

如果管道中没有任何东西,此任务将无限期挂起......

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

We can prevent this though by doing a timeout readfor the first character. If it times out, the return code will be greater than 128 and we'll know the STDIN pipe (a.k.a /dev/stdin) is empty.

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

Otherwise, we get the rest of STDIN by...

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

  • setting IFSto NULL for just the readcommand
  • turning off escapes with -r
  • eliminating read's delimiter with -d ''.
  • and finally, appending that to the character we got initially
  • IFS仅为read命令设置为 NULL
  • 关闭转义 -r
  • 消除读取的分隔符-d ''
  • 最后,将它附加到我们最初得到的角色上

Thus...

因此...

__=""
_stdin=""

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

This technique avoids using var="$(command ...)"Command Substitution which, by design, will always strip off any trailing newlines.

这种技术避免使用var="$(command ...)"命令替换,它在设计上总是会去掉任何尾随的换行符。

If Command Substitution is preferred, to preserve trailing newlines we can append one or more delimiter characters to the output inside the $()and then strip them off outside.

如果首选命令替换,为了保留尾随换行符,我们可以将一个或多个定界符附加到输出内部$(),然后将它们从外部剥离。

For example ( note $(parens)in first command and ${braces}in second )...

例如$(parens)在第一个命令和${braces}第二个命令中注意)......

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

回答by DocSalvager

Yes it works for me too. Thanks.

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

myvar=`cat`

is the same as

是相同的

myvar=`cat /dev/stdin`

Well yes. From the bashman page:

嗯,是。从bash手册页:

Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and, when history expansion is enabled, !. The characters $ and ` retain their special meaning within double quotes.

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

回答by Ingo Karkat

If you do care about preserving trailing newlines at the end of the output, use this:

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

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

This uses the trick from here.

这使用了这里的技巧。