如何从STDIN读取多行到一个变量中?


24

我一直在搜寻这个问题无济于事。我正在这里使构建过程自动化,而我要做的就是获取版本号和对构建的简短描述,该描述可能是多行的。运行该系统的系统是OSX 10.6.8。

我已经看到了从使用CAT到根据需要处理每一行的所有内容。我不知道该使用什么以及为什么使用。

尝试次数

read -d '' versionNotes

如果用户必须使用退格键,则会导致输入乱码。另外,也没有终止输入的好方法,因为^ D不会终止,而^ C只会退出进程。

read -d 'END' versionNotes

可以...但是如果需要退格键,输入仍会显示乱码。

while read versionNotes
do
  echo "  $versionNotes" >> "source/application.yml"
done

无法正确结束输入(因为我来不及查找与空字符串匹配的内容)。


您是从用户那里获得此信息的,对吗?
glenn jackman 2012年

正确; 我希望用户在执行脚本时在终端中输入此信息。
罗伯特K

1
我宁愿说,您还没有说清楚。
poige 2012年

Answers:


20

man bash 提到«…

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

…»

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

我同意这是值得一提的- echo "$myVar"将显示输入的内容。


1
多行输入后如何停止?如果按Ctrl C,它会停止,但不会保存该变量!
Nikhil

2
UNIX®终端确实具有“纪律”:en.wikipedia.org/wiki/Line_discipline• 查明“ eof”是什么意思•请阅读man stty,找出如何获取当前设置
poige

2
ctrl -d停止。
freb 18-10-23

9

尝试这个:

user@host:~$ read -d '' x <<EOF
> mic
> check
> one
> two
> EOF

没有换行符:

user@host:~$ echo $x
mic check one two

换行符:

user@host:~$ echo "$x"
mic
check
one
two

2
-d ''正是我所需要的。谢谢
Bruno Bronosky

@布鲁诺,我的荣幸;这是一个棘手的问题。尤其是乍一看,它看起来相当标准。一旦掌握了各种特质,它可能会非常有用。
声音


2

通过解决每一行,直到我提出一个空白行,我已经解决了这个问题。对于我的情况,它足够好用。但是,如果有人想添加更好的解决方案,请随时这样做。

echo "---
notes: |" > 'version.yml'

while read line
do
  # break if the line is empty
  [ -z "$line" ] && break
  echo "  $line" >> "source/application.yml"
done

使用read -r代替。
适配器

2

您可以启动vim,pico等编辑器...

${VISUAL:-${EDITOR:-vi}} source/application.yml

嗯...这怎么以OP的方式回答了OP的问题?
适配器

他可以从脚本启动编辑器。
Mircea Vutcovici 2012年

那到底完成了什么?他想用文字脚本文件,不写信息一个文件中。
适配器

他不想从用户那里读取文本并将其写入文件。请阅读添加到问题的评论。
Mircea Vutcovici 2012年

1

首先进行一些更正:

  1. 为了允许在线使用-e使用readline的“ edition” (因此您具有bash历史记录和所有编辑功能)
  2. -d只需要一个字符。例如,从“ END”开始取“ E”,每当用户输入“ E”时,读数就会停止(我想那不是您想要的...)

有几种方法可以做到这一点。我会逐行阅读并在找到空行时停止(尽管您可以设置任何停止词):

unset tmp
while :
do 
 read line
 [[ $line == "" ]] && tmp="${tmp:0:$((${#tmp}-1))}" && break
 tmp="$tmp"$line$'\n'
done

0

您有几种方法。

最简单的方法之一是:

MYVAR=$(yourcommand)
echo $"MYVAR"

例如:

MYVAR=$(ls /)
echo $"MYVAR"

除非我没有执行像LS这样的shell命令。我要求用户输入多行内容。
罗伯特K

这是非常糟糕的做法;不处理ls!的输出!
适配器

@adaptr我们之前已经听说过所有内容,请介意建议一个好选择吗?
声音

0

我们正在使用使用xargs和ctrl-d进行破坏的构造。我对它并不完全满意,但是它确实可以完成多行用户输入并将其填充到变量中的工作(格式化完好无损)。(第一个和第三个赋值在xargs输入的内容周围添加引号。)

    printf "\\033[1mWhen finished hit ctrl-d on a new line to proceed.\\033[0m  \\n\\n" 
    # this will load the user's input into a variable instead of a file 
    reminderBody="\"" 
    reminderBody+=$( xargs -0 ) 
    reminderBody+="\"" 

我们将hinterBody用作通过邮件(通过bash)发送的电子邮件的主题。


-1

请参阅:http : //tldp.org/LDP/abs/html/internal.html#READR

使用read并注意,如果用\换行符结束一行,则将被忽略。因此,您可以执行以下操作:

#!/ bin / bash

读取-p“ version:”版本
回声$版本

#输入一些输入,并用“ \”结束长行,然后在末尾简单输入
阅读-p“ description:”描述
echo -e“ $ version \ n $ description >> yourfile.txt

如果我只想忽略带有换行符的段落,则可以。但是,由于这是生成脚本的发行说明列表,因此我需要能够保留这些换行符。例如,我可能会尝试输入项目符号列表。
罗伯特K

ABS是一个可怕的怪兽。90%是完全错误的。
适配器

这并不是不好。
声音
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.