简体   繁体   English

Bash-将变量分配给循环中的命令输出

[英]Bash - assign variables to output of a command in a loop

I've got an application that runs and defines the devices on a system. 我有一个运行并定义系统上设备的应用程序。 The output looks something like this: 输出看起来像这样:

./show-devices 192.168.1.2 | grep volume

/dev/sda        volumeid-65
/dev/sdb        volumeid-81
/dev/sdc        volumeid-92

What I'm trying to do is run the application in a loop and assign variables like so: 我想做的是在循环中运行应用程序并分配变量,如下所示:

sda=volumeid-65
sdb=volumeid-81
sdc=volumeid-92

Then, be able to use the $sda, $sdb, and $sdc variables later on in the script. 然后,稍后可以在脚本中使用$ sda,$ sdb和$ sdc变量。 Not all outputs are the same. 并非所有输出都相同。 Some machines will only have one volume, some will have more. 有些机器只有一个音量,有些则更大。 All suggestions are welcome. 欢迎所有建议。 I've tried many combinations of a for loop and don't appear to be getting anywhere. 我已经尝试了for循环的许多组合,但似乎并没有取得进展。 Thank you! 谢谢!

How about: 怎么样:

eval `./show-devices 192.168.1.2 | grep volume | while read d v ;do
    echo $(basename $d)=$v
done`

However, you'll not be sure of the names of the variables. 但是,您将不确定变量的名称。 So it's better to use an associative array: 因此,最好使用关联数组:

# declare the array
declare -A volumes

# Assign values to the array
eval `./show-devices 192.168.1.2 | grep volume | while read d v ;do
    echo volumes[$(basename $d)]=$v
done`

# Use the array
for i in "${!volumes[@]}"; do
    echo "Key:$i , Value:${volumes[$i]}"
    # Declare all the variables with the values as asked by question
    eval $i=${volumes[$i]}
done

Explaination : | while read dv | while read dv | while read dv loops over the output of the previous command reading 2 values per line. | while read dv循环遍历前一个命令的输出,每行读取2个值。 basename $d gives me the base name of the device and $v contains the volume associated with the device. basename $d给我设备的基本名称,$ v包含与设备关联的卷。 This is assigned into the volumes associative array declared with declare -A volumes . 这被分配给用declare -A volumes声明的volumes关联数组。 The while loop runs ins a sub-shell and prints volumes[sda]=... and eval evaluates this in the current shell, actually assigning the value. while循环在子外壳程序中运行并打印volumes[sda]=...eval在当前外壳程序中对此进行评估,实际上是在分配值。

Usage : The for loop is a usage example. 用法for循环是一个用法示例。 "${!volumes[@]}" is the list of keys for the volumes array, and the for loop loops over them and prints the value associated with each key in the volumes array. "${!volumes[@]}"volumes数组的键列表,并且for循环在它们上循环并打印与volumes数组中的每个键关联的值。

Edits : 编辑

  • Modified the while loop to echo the assigment and eval the whole thing (to get around the subshell being spawned by the pipe. 修改了while循环,以呼应分配并eval整个事情(以避开由管道生成的子外壳。

  • Added usage info 添加了用法信息

  • Added exact solution asked in question 添加了有问题的确切解决方案

source <(
    ./show-devices 192.168.1.2 |
    sed -rn '/volume/{s#/dev/([^[:space:]]+)[[:space:]]+#\1=#;p}'
)

This runs your command, passes it through sed to format it like shell assignments, and then uses a process substitution to treat the output like a file which is sourced into the current shell. 这将运行您的命令,将其传递给sed以将其格式化为类似于外壳分配的格式,然后使用进程替换将输出像将其视为源于当前外壳的文件一样对待。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM