while-loop 似乎不记得变量更新 - 不涉及管道

while-loop 似乎不记得变量更新 - 不涉及管道

我正在使用标准 Mate 桌面运行 LMDE 2(“Betsy”),并且有以下脚本:

#!/bin/bash
# This script starts a specified terminal-binary in "Always on Top"-mode
# The assumption is, that 'wmctrl -l' sorts windows with the 
# in such a way, that the more recently a window has been created, 
# the lower it will be on the list ( compared to windows with the 
# same title).
#
# This is my assumption based on a short observation. The window 
# ids are probably given out in ascending hex numbers
# 
# Note: Using the pid will not help, since all terminals seem to
# be having the same pid
term_title_def='Terminal'
term_title='Terminal_top'
term_cmd="mate-terminal --title=$term_title"

# start terminal, wait for window  to appear and get id of most recently created window
# NOTE: a possible wrap-around of window ids has not been considered here!
eval $term_cmd
win_id=''
while [[ -z $win_id ]]; do
    win_id=$(wmctrl -l | grep "[[:blank:]]$term_title\$" | tail -n 1 | awk '{ print $1 }')
done

# DEBUG
touch /tmp/$win_id

# rename, set as "Always on top"
wmctrl -ir $win_id -T "$term_title_def"
wmctrl -ir $win_id -b add,above
wmctrl -ia $win_id

ps aufx不知何故,重新启动后首次从 MATE 面板链接运行该脚本时,该脚本永远不会退出 while 循环(使用 检查)。随后的调用按预期工作,即链接执行我想要的操作(请参阅上面的脚本注释)。

因此,不知何故,在启动 MATE 后,我想(?)win_id在 -test 中没有正确扩展。while或类似的东西。

这是为什么?
我现在会尝试类似的方法while true; do stuff; break; done,希望它能起作用......

更新:用以下内容
替换上面的循环while

while true; do
    win_id=$(wmctrl -l | grep "[[:blank:]]$term_title\$" | tail -n 1 | awk '{ print $1 }')
    [[ $win_id ]] && break
done

没有改变任何东西。脚本仍然陷入无限循环......

答案1

我不明白这怎么行。当你跑步时

eval $term_cmd 

您将打开一个终端窗口,并且在您关闭它之前脚本不会执行任何其他操作。你需要的是:

$term_cmd &

在后台运行它(并且不要使用eval,它不是必需的)。然后,您也不需要选择wmctrl输出的最后一行。您正在设置终端标题,因此将其设置为唯一的内容grep

#!/bin/bash
# This script starts a specified terminal-binary in "Always on Top"-mode
# The assumption is, that 'wmctrl -l' sorts windows with the 
# in such a way, that the more recently a window has been created, 
# the lower it will be on the list ( compared to windows with the 
# same title).
#
# This is my assumption based on a short observation. The window 
# ids are probably given out in ascending hex numbers
# 
# Note: Using the pid will not help, since all terminals seem to
# be having the same pid
term_title_def='Terminal'
term_title="Terminal_top_$$" ## Use the script's PID for a unique title
term_cmd="mate-terminal --title=$term_title"

## Start terminal. No need to wait, the loop will run until
## the terminal has been opened
$term_cmd &

win_id=''

while [[ -z "$win_id" ]]; do
    ## No need for '[[:blank:]]' and \$, you are using a unique title,
    ## keep the regex general. 
    win_id=$(wmctrl -l | grep "$term_title" | awk '{ print $1 }')
done
# DEBUG
touch /tmp/$win_id

# rename, set as "Always on top"
wmctrl -ir $win_id -T "$term_title_def"
wmctrl -ir $win_id -b add,above
wmctrl -ia $win_id

答案2

while 循环在子 shell 中执行,因此对子 shell 中的变量所做的任何修改都不会报告到父 shell 中:https://stackoverflow.com/questions/16854280/modifying-variable-inside-while-loop-is-not-remembered

对于我这边的第二个问题,我有:

$ while true; do toto=plop; echo $toto; [[ $toto ]] && break ; done 
plop

$win_id所以我确实认为你对循环内部的定义有一个真正的问题。

相关内容