2011-10-06 93 views
44

当我尝试在Bash中使用read命令是这样的:如何在Bash中使用读命令?

echo hello | read str 
echo $str 

没有呼应,而我认为应该str包含字符串hello。任何人都可以帮助我理解这种行为吗?

回答

49

你的脚本命令中的read没问题。但是,您在管道中执行它,这意味着它位于子shell中,因此它读取的变量在父shell中不可见。您可以

  • 移动在子shell脚本的休息,太:

    echo hello | { read str 
        echo $str 
    } 
    
  • ,或者使用命令替换来获取变量的值从子shell的

    str=$(echo hello) 
    echo $str 
    

    或稍微复杂一些的例子(抓取ls的第二个元素)

    str=$(ls | { read a; read a; echo $a; }) 
    echo $str 
    
+0

真棒例子!我不得不在OSX上稍微调整一下,在大括号内放置空格,在echo之后加一个分号,如下所示:str = $(ls | {read a; read a; echo $ a;}) –

+5

是“读一个;读一个;”需要*两次*? – javadba

+0

@javadba:不需要两次。给出的例子从'ls'返回* second *项。用一个'读一个'你会得到第一个项目。不要问我回答者为什么选择这个例子。 – Fritz

3

的价值消失,因为读命令在一个单独的子shell中运行:Bash FAQ 24

-5

你需要管?

echo -ne "$MENU" 
read NUMBER 
+1

-1:你的'echo'和'read'命令没有任何连接。 –

+0

这不好吗?它的工作原理... – mmrtnt

+0

海报显然需要一种自动方式来填充变量,而无需手动输入。 –

33

其他庆典的替代品,不涉及一个子shell:

read str <<END    # here-doc 
hello 
END 

read str <<< "hello"  # here-string 

read str < <(echo hello) # process substitution 
+2

你也可以在这里使用这个字符串的过程,比如'read ABC <<< $(echo'aaa bbb ccc')' – maxpolk

8

典型用法可能是:

i=0 
echo -e "hello1\nhello2\nhello3" | while read str ; do 
    echo "$((++i)): $str" 
done 

和输出

1: hello1 
2: hello2 
3: hello3 
2

为了把我的两个美分:KSH,read荷兰国际集团作为是一个变量工作,因为根据the IBM AIX documentation,KSH的read确实影响当前shell环境:

的读取指令shell变量的设置会影响当前shell执行环境。

这只是导致我花了好几分钟弄清楚为什么与read结束一行代码,我曾经使用过亿万倍AI​​X上没有工作在Linux上...这是因为KSH做保存到当前环境,而BASH不会!

0

另一个替代方法是使用printf函数。

printf -v str 'hello' 

此外,该构建体,通过使用单引号酌情的结合,有助于避免子shell和其他形式的内插引用的多逃逸的问题。

+0

如果你正在努力实现这一切,那么你最好'str =' hello'。我认为这里的要点是将一个命令的输出捕获到一个变量中。 – mc0e

0

我真的只使用读取“而”和做循环:

echo "This is NOT a test." | while read -r a b c theRest; do 
echo "$a" "$b" "$theRest"; done 

这是一个测试。
对于它的价值,我看到了建议总是使用-r与bash中的读取命令。