bash 从函数设置多个变量的方法

Dav*_* W. 1 bash function

我想以更自上而下的设计编写一个 shell 脚本。我曾经使用 Kornshell 脚本来执行此操作。我定义了可能返回多组变量的各种函数(例如,一个getopts函数)。然后我可以在主程序中使用这些函数来设置我想要的变量。

不幸的是,BASH 和 Kornshell 处理此实例的方式似乎有所不同。这是我在 Kornshell 中运行的一个简单脚本。我的函数foo返回四个值。我将把这四个值读入主程序中的变量中:

#!/bin/ksh

function foo {
    echo "this:that:the:other"
}

IFS=":"
foo | read one two three four
echo "one = $one"
echo "two = $two"
echo "three = $three"
echo "four = $four"
Run Code Online (Sandbox Code Playgroud)

这会产生:

one = this
two = that
three = the
four = other
Run Code Online (Sandbox Code Playgroud)

奇迹般有效。让我们使用 BASH 而不是 Kornshell 来尝试相同的程序:

#!/bin/bash

function foo {
    echo "this:that:the:other"
}

IFS=":"
foo | read one two three four
echo "one = $one"
echo "two = $two"
echo "three = $three"
echo "four = $four"
Run Code Online (Sandbox Code Playgroud)

这会产生:

one = 
two = 
three = 
four = 
Run Code Online (Sandbox Code Playgroud)

读取的管道根本不起作用。让我们尝试一下这里的内容:

#!/bin/bash

function foo {
    echo "this:that:the:other"
}

IFS=":"
read one two three four<<<$(foo)
echo "one = $one"
echo "two = $two"
echo "three = $three"
echo "four = $four"
Run Code Online (Sandbox Code Playgroud)

我得到:

one = this that the other
two =
three =
four =
Run Code Online (Sandbox Code Playgroud)

允许$one设置,但不允许设置其他变量。奇怪的是,冒号被从字符串中删除了。让我们从返回值中删除冒号:

#!/bin/bash

function foo {
    echo "this that the other"
}

read  one two three four<<<$(foo)
echo "one = $one"
echo "two = $two"
echo "three = $three"
echo "four = $four"

one = this
two = that
three = the
four = other
Run Code Online (Sandbox Code Playgroud)

那确实有效。每个变量都是从 function 中读入的foo

我究竟做错了什么?为什么设置似乎不像IFS我在 BASH 中想象的那样工作?或者有更好的方法来做到这一点吗?

fed*_*qui 6

你必须引用:

#!/bin/bash

function foo {
    echo "this:that:the:other"
}

IFS=":"
read one two three four<<<"$(foo)"
                          ^      ^
Run Code Online (Sandbox Code Playgroud)

执行后返回:

$ ./a
one = this
two = that
three = the
four = other
Run Code Online (Sandbox Code Playgroud)

关于这个不起作用:

#!/bin/bash

...    

IFS=":"
foo | read one two three four
echo "one = $one"
Run Code Online (Sandbox Code Playgroud)

我想这是因为它IFS是在与具有read. 另外,通过管道传递fooread似乎并不是read在 bash 中给出字符串的方法。

为此,请打开一个新 shell,如Bash 脚本所示,从 stdin 管道读取值

$ foo | { IFS=":"; read one two three four; echo "one = $one"; echo "two = $two"; echo "three = $three"; echo "four = $four"; }
one = this
two = that
three = the
four = other
Run Code Online (Sandbox Code Playgroud)

  • 请记住,“read”与“IFS”交互的方式也存在一个可能适用于此的错误。它预计将在 4.3 中修复。 (2认同)