热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Bash脚本,从stdin管道中读取值-Bashscript,readvaluesfromstdinpipe

Iamtryingtogetbashtoprocessdatafromstdinthatgetspipedit,butnoluck,whatImeanisn

I am trying to get bash to process data from stdin that gets piped it, but no luck, what I mean is none of the following work:

我正在尝试让bash处理来自stdin的数据,这些数据会被传输出去,但是没有运气,我的意思是没有以下工作:

echo "hello world" | test=($(

where I want the output to be test=hello world. Note I've tried putting "" quotes around "$test" that doesn't work either.

我希望输出是test=hello world。注意,我试过在“$test”周围加上“”引号,这也不管用。

14 个解决方案

#1


136  

Use

使用

IFS= read var <

You can trick read into accepting from a pipe like this:

你可以通过像这样的管道欺骗来接受:

echo "hello world" | { read test; echo test=$test; }

or even write a function like this:

或者写一个这样的函数:

read_from_pipe() { read "$@" <&0; }

But there's no point - your variable assignments may not last! A pipeline may spawn a subshell, where the environment is inherited by value, not by reference. This is why read doesn't bother with input from a pipe - it's undefined.

但是没有意义——你的变量分配可能不会持续太久!管道可以生成一个子shell,其中环境是由值继承的,而不是引用。这就是为什么read不麻烦来自管道的输入——它没有定义。

FYI, http://www.etalabs.net/sh_tricks.html is a nifty collection of the cruft necessary to fight the oddities and incompatibilities of bourne shells, sh.

这是一组巧妙的cruft集合,用来对抗bourne shell的古怪和不兼容。

#2


98  

if you want to read in lots of data and work on each line separately you could use something like this:

如果你想要阅读大量的数据并分别处理每一行,你可以使用以下方法:

cat myFile | while read x ; do echo $x ; done

if you want to split the lines up into multiple words you can use multiple variables in place of x like this:

如果你想把这些行分割成多个单词,你可以用多个变量来代替x:

cat myFile | while read x y ; do echo $y $x ; done

alternatively:

另外:

while read x y ; do echo $y $x ; done 

But as soon as you start to want to do anything really clever with this sort of thing you're better going for some scripting language like perl where you could try something like this:

但是一旦你开始想要做任何真正聪明的事情你最好去做一些脚本语言比如perl你可以尝试这样的方法:

perl -ane 'print "$F[0]\n"' 

There's a fairly steep learning curve with perl (or I guess any of these languages) but you'll find it a lot easier in the long run if you want to do anything but the simplest of scripts. I'd recommend the Perl Cookbook and, of course, The Perl Programming Language by Larry Wall et al.

perl有一个相当陡峭的学习曲线(或者我猜这些语言中的任何一种),但是如果您想要做除了最简单的脚本之外的任何事情,那么从长远来看,您会发现它要容易得多。我推荐Larry Wall等人的Perl Cookbook和Perl编程语言。

#3


31  

read won't read from a pipe (or possibly the result is lost because the pipe creates a subshell). You can, however, use a here string in Bash:

read不会从管道中读取(或者由于管道创建子shell而丢失结果)。但是,您可以在Bash中使用here字符串:

$ read a b c <<<$(echo 1 2 3)
$ echo $a $b $c
1 2 3

#4


30  

This is another option

这是另一个选择

$ read test <<(echo hello world)

$ echo $test
hello world

#5


26  

I'm no expert in Bash, but I wonder why this hasn't been proposed:

我不是Bash的专家,但我想知道为什么没有提出:

stdin=$(cat)

echo "$stdin"

One-liner proof that it works for me:

用一句话证明它对我有效:

$ fortune | eval 'stdin=$(cat); echo "$stdin"'

#6


17  

bash 4.2 introduces the lastpipe option, which allows your code to work as written, by executing the last command in a pipeline in the current shell, rather than a subshell.

bash 4.2引入了lastpipe选项,通过在当前shell中的管道中执行最后一个命令,而不是子shell中执行,从而允许代码按照编写的方式工作。

shopt -s lastpipe
echo "hello world" | read test; echo test=$test

#7


11  

The syntax for an implicit pipe from a shell command into a bash variable is

从shell命令到bash变量的隐式管道的语法。

var=$(command)

or

var=`command`

In your examples, you are piping data to an assignment statement, which does not expect any input.

在您的示例中,您正在将数据传输到一个赋值语句,该语句不要求任何输入。

#8


4  

The first attempt was pretty close. This variation should work:

第一次尝试非常接近。这个变化应该工作:

echo "hello world" | { test=$(

and the output is:

和输出是:

test=hello world

测试= hello world

You need braces after the pipe to enclose the assignment to test and the echo.

在管道之后,您需要使用背带来封装要测试的赋值和回波。

Without the braces, the assignment to test (after the pipe) is in one shell, and the echo "test=$test" is in a separate shell which doesn't know about that assignment. That's why you were getting "test=" in the output instead of "test=hello world".

没有括号,要测试的赋值(在管道之后)在一个shell中,而echo“test=$test”位于一个不知道该赋值的独立shell中。这就是为什么在输出中得到“test=”而不是“test=hello world”的原因。

#9


4  

In my eyes the best way to read from stdin in bash is the following one, which also lets you work on the lines before the input ends:

在我看来,在bash中阅读stdin的最佳方式是以下一种,它还允许您在输入结束前处理行:

while read LINE; do
    echo $LINE
done 

#10


3  

Piping something into an expression involving an assignment doesn't behave like that.

在涉及到赋值的表达式中管道一些东西的行为不是这样的。

Instead, try:

相反,尝试:

test=$(echo "hello world"); echo test=$test

#11


2  

The following code:

下面的代码:

echo "hello world" | ( test=($(

will work too, but it will open another new sub-shell after the pipe, where

也会起作用,但它会在管道后面再开一个新的子壳,在哪里?

echo "hello world" | { test=($(

won't.

不会的。


I had to disable job control to make use of chepnars' method (I was running this command from terminal):

我必须禁用作业控制才能使用chepnars的方法(我在终端上运行这个命令):

set +m;shopt -s lastpipe
echo "hello world" | read test; echo test=$test
echo "hello world" | test="$(

Bash Manual says:

Bash手册说:

lastpipe

lastpipe

If set, and job control is not active, the shell runs the last command of a pipeline not executed in the background in the current shell environment.

如果设置并没有激活作业控制,则shell将运行当前shell环境中未在后台执行的管道的最后一个命令。

Note: job control is turned off by default in a non-interactive shell and thus you don't need the set +m inside a script.

注意:在非交互式shell中默认关闭作业控制,因此您不需要在脚本中使用set +m。

#12


1  

I think you were trying to write a shell script which could take input from stdin. but while you are trying it to do it inline, you got lost trying to create that test= variable. I think it does not make much sense to do it inline, and that's why it does not work the way you expect.

我认为您试图编写一个shell脚本,它可以从stdin中获取输入。但是当您尝试内联地执行它时,您在尝试创建test=变量时迷失了方向。我认为内联操作没有多大意义,这就是为什么它不能按照预期的方式工作。

I was trying to reduce

我试着减少

$( ... | head -n $X | tail -n 1 )

to get a specific line from various input. so I could type...

从各种输入中获取特定的行。所以我可以类型……

cat program_file.c | line 34

so I need a small shell program able to read from stdin. like you do.

所以我需要一个能够从stdin中读取的小shell程序。像你一样。

22:14 ~ $ cat ~/bin/line 
#!/bin/sh

if [ $# -ne 1 ]; then echo enter a line number to display; exit; fi
cat | head -n $1 | tail -n 1
22:16 ~ $ 

there you go.

那就这样吧。

#13


1  

Because I fall for it, I would like to drop a note. I found this thread, because I have to rewrite an old sh script to be POSIX compatible. This basically means to circumvent the pipe/subshell problem introduced by POSIX by rewriting code like this:

因为我喜欢它,我想写个便条。我找到了这个线程,因为我必须重写一个旧的sh脚本才能与POSIX兼容。这基本上是通过重写代码来绕过POSIX引入的管道/子shell问题:

some_command | read a b c

into:

成:

read a b c <

And code like this:

和代码是这样的:

some_command |
while read a b c; do
    # something
done

into:

成:

while read a b c; do
    # something
done <

But the latter does not behave the same on empty input. With the old notation the while loop is not entered on empty input, but in POSIX notation it is! I think it's due to the newline before EOF, which cannot be ommitted. The POSIX code which behaves more like the old notation looks like this:

但后者在空输入上的行为并不相同。使用旧的表示法,while循环不是在空输入中输入的,而是在POSIX表示法中输入的!我认为这是由于EOF之前的换行,不能省略。POSIX代码表现得更像旧的符号是这样的:

while read a b c; do
    case $a in ("") break; esac
    # something
done <

In most cases this should be good enough. But unfortunately this still behaves not exactly like the old notation if some_command prints an empty line. In the old notation the while body is executed and in POSIX notation we break in front of the body.

在大多数情况下,这应该足够好。但不幸的是,如果some_command打印空行,这仍然不完全像旧的表示法。在旧的表示法中,当身体被执行,而在POSIX表示法中,我们在身体前面被打断。

An approach to fix this might look like this:

解决这个问题的方法可能是这样的:

while read a b c; do
    case $a in ("something_guaranteed_not_to_be_printed_by_some_command") break; esac
    # something
done <

#14


0  

How about this:

这个怎么样:

echo "hello world" | echo test=$(cat)

推荐阅读
author-avatar
谭小牙笑不漏齿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有