从while循环中的变量执行命令或从while循环导出变量

时间:2016-10-15 03:40:17

标签: bash shell while-loop moonlight

我编写了一个带有while循环的脚本,没有意识到从while循环中获取变量的难度。

我想要做的是在while循环完成所需的循环之后运行while循环保存在'stream'变量中的命令(参见下面的代码)。我正在使用这个脚本来检测连接的游戏控制器并创建一个初始化月光的命令,这是一个覆盆子pi的程序,它允许我通过Nvidia Game Stream流式传输,具有不同的控制器类型。

#!/bin/bash

stream="moonlight stream -1080 -app Steam"
device=none

event=0

Player="-input /dev/input/event"

XbElite="-mapping /opt/retropie/configs/moonlight/XboxOne.map"
PlSt3="-mapping /opt/retropie/configs/moonlight/PS3.map"

XboxElite="N\:\ Name\=\"Microsoft\ X\-Box\ One\ Elite\ pad\""
PS3="N\:\ Name\=\"PLAYSTATION\(R\)3\ Controller\""

cat /proc/bus/input/devices | \
while read CMD; do
    line=$(echo "$CMD" | sed 's/ /\\ /g; s/:/\\:/g; s/(/\\(/g; s/)/\\)/g; s/-/\\-/g; s/=/\\=/g')
    if [ "$line" = "$XboxElite" ]; then
        echo Xbox
        device=xboxElite
        if [ "$device" = "xboxElite" ]; then
            stream="$stream $XbElite $Player$event"
            event=$((event+1))
            device=none
        fi
    elif [ "$line" = "$PS3" ]; then
        echo PS3
        device=ps3
        if [ "$device" = "ps3" ]; then
            stream="$stream $PlSt3 $Player$event"
            event=$((event+1))
            device=none
        fi
    fi
done
echo $stream #put here as a placeholder to see the final command in the variable. Currently printing: 'moonlight stream -1080 -app Steam'

我意识到这可能不是最干净的方式,或者代码甚至接近尽可能好的写入,但由于我以前几乎没有任何类型的编码经验,这就是我能做到的暂时管理。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

那么,将它作为命令运行的方法就是删除echo

done
$stream

...除了你不能,因为while循环位于管道的右侧。这意味着它运行在"子shell"并且不能在其父shell(循环外)中产生副作用;循环退出后,$stream将恢复到循环之前的状态。

为了使循环与周围代码保持相同的环境而不是自己的子shell,您需要直接从文件中读取而不是使用管道:

# no `cat` command here.  No pipe.
while read CMD; do
...
done </proc/bus/input/devices #this replaces the `cat |`.
$stream

在一般情况下,当动态构建命令以便稍后运行时,您将遇到引用或空格或其他特殊字符的问题。如果在数组中而不是字符串中构建命令,最容易避免这些问题。在数组中构建和运行命令的语法如下所示:

stream=(moonlight stream -1080 -app Steam)
...
while read CMD; do
  ...
  stream+=("$XbElite" "$Player$event")
  ...
  stream+=("$PlSt3" "$Player$event")
...
done </proc/bus/input/devices
"${stream[@]}"

答案 1 :(得分:0)

Mark Reed 说的是什么,主循环也可以简化:

sed 's/\([-:\( )=]\)/\\&/g' /proc/bus/input/devices | \
while read line; do
    if [ "$line" = "$XboxElite" ]; then
        echo Xbox
        stream="$stream $XbElite $Player$event"
        event=$((event+1))
    elif [ "$line" = "$PS3" ]; then
        echo PS3
        stream="$stream $PlSt3 $Player$event"
        event=$((event+1))
    fi
done