如何在bash中将一行中的两个值放入两个变量中?

时间:2015-02-20 18:11:02

标签: bash

例如,而不是做

start=`commandforstdout | awk {'print $2'}`
end=`commandforstdout | awk {'print $5'}`

有没有办法存储

`commandforstdout | awk {'print $2, $5'}`

分成两个不同的变量,而不必再次运行命令?只是为了提高效率...

3 个答案:

答案 0 :(得分:5)

read内置使用流程替换

read start end < <(commandforstdout | awk {'print $2, $5'})

甚至没有awk(感谢@gniourf_gniourf):

read -r _ start _ _ end _ < <(commandforstdout)

答案 1 :(得分:2)

这种无需协同处理或基本原理的便携式方法:

set -- $(commandforstdout | awk '{print $2, $5}')
start=$1 end=$2

如果您告诉我们commandforstdout的输出,这可能会更容易。可能是那个

set -- $(commandforstdout)
start=$2 end=$5
甚至可以节省昂贵的叉子和管道。正如gniourf_gniourf正确地指出的那样,如果结果包含glob字符,则路径名扩展可能会受到阻碍。如果这是一个问题,请在第一个set -fset之前使用set +f,如果您稍后需要进行路径名扩展。

答案 2 :(得分:2)

补充现有的有用答案:

简单的管道解决方案(commandforstdout | read ...)不起作用的原因是管道中的所有命令默认都在 sub shell 中运行,以便管道中的read命令创建的变量在管道之后可见。

但是,在 bash 4.2 + 上,启用 shell选项lastpipe会导致 last 管道段在当前<中运行/ em> shell ,允许read创建当前shell可见的变量。

示例:

# bash 4.2+: Turn on shell option that runs the *last* pipeline segment in the
#            *current shell* rather than in a *subshell*.
shopt -s lastpipe

# Read the two words piped via stdin into two variables.
# Since option `lastpipe` is on, the variables are created in the *current* shell.
echo 'START END' | read -r start end  

echo "[$start] [$end]"  # -> '[START] [END]'

注意:lastpipe仅在 off 的作业控制时有效,默认情况下在非交互式shell中为true(例如,在脚本中),但在交互式shell 中却不是这样;要以交互方式测试上述示例,您必须关闭作业控制(暂时):
set +m; shopt -s lastpipe && echo 'START END' | read -r start end; echo "[$start] [$end]"; set -m