在Bash中获取鼠标所在屏幕名称的更简便方法咨询
问题:简化获取鼠标所在屏幕名称的Bash脚本
我写了一段Bash脚本,通过xdotool获取鼠标位置,结合xrandr的屏幕配置来判断鼠标所在的屏幕名称。但感觉这个实现有点繁琐,想咨询有没有更简便的方式——比如利用内置函数,或者优化现有脚本的逻辑?
原脚本如下:
#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' ## 获取鼠标位置并直接保存到变量X/Y eval $(xdotool getmouselocation --shell) ### 获取已连接并激活的屏幕尺寸/布局 ### 正则匹配格式示例:1920x1080+0+0 screens=$(xrandr | grep -oP '^\w+.* (\d+x\d+\+\d+\+\d+)') ## 遍历屏幕,判断鼠标位置是否在屏幕内 for screen in $screens do name=$(echo "$screen" | grep -oP "^\w+") scr_info=$(echo $screen | awk '{print $NF}') # 提取屏幕宽/高及偏移量 screen_w=$(echo $scr_info | awk -F '[x+]' '{print $1}') screen_h=$(echo $scr_info | awk -F '[x+]' '{print $2}') screen_x=$(echo $scr_info | awk -F '[x+]' '{print $3}') screen_y=$(echo $scr_info | awk -F '[x+]' '{print $4}') # 判断鼠标坐标是否在屏幕范围内 if [ "$X" -ge "$screen_x" ] && [ "$X" -lt "$(( screen_x + screen_w))" ] && [ "$Y" -ge "$screen_y" ] && [ "$Y" -lt "$(( screen_y + screen_h))" ] then echo "$name" fi done
回答
你的思路是对的,但原脚本里重复调用grep和awk会产生大量子进程,既不高效也不够简洁。这里提供两个实用的优化方向:
方向1:简化现有脚本,大幅减少子进程开销
我们可以把xrandr解析、鼠标坐标读取和范围判断的逻辑合并,用更少的进程完成任务,同时避开有安全风险的eval命令:
优化后的脚本:
#!/usr/bin/env bash set -euo pipefail IFS=$'\n\t' # 安全读取鼠标坐标到X、Y变量,替代eval read -r X Y <<< "$(xdotool getmouselocation | awk '{gsub(/X:|Y:/,"",$1$2); print $1, $2}')" # 一次性完成xrandr解析与屏幕匹配 xrandr | awk -v mx="$X" -v my="$Y" ' / connected/ { # 提取屏幕名称 screen_name = $1 # 拆分分辨率与偏移参数(格式:宽x高+X偏移+Y偏移) split($NF, pos, /[x+]/) scr_w = pos[1] scr_h = pos[2] scr_x = pos[3] scr_y = pos[4] # 判断鼠标是否在当前屏幕范围内 if (mx >= scr_x && mx < scr_x + scr_w && my >= scr_y && my < scr_y + scr_h) { print screen_name exit # 找到目标屏幕后直接退出,避免无效遍历 } } '
核心优化点:
- 用
read+awk替代eval读取鼠标坐标,避免潜在安全风险; - 将所有解析、判断逻辑交给单进程
awk处理,彻底消除循环内的重复子进程调用; - 精准匹配
connected状态的屏幕,避免原脚本可能误匹配的非激活屏幕; - 找到目标屏幕后立即退出,减少不必要的计算。
方向2:使用X11专属的极简工具链(兼容性需注意)
如果你使用的是支持标准X11属性的窗口管理器,可以用xprop直接获取当前屏幕名称,代码更短,但兼容性不如第一种方案(部分轻量WM可能不支持相关属性):
# 通过窗口属性直接定位屏幕名称 active_win=$(xprop -root _NET_ACTIVE_WINDOW | awk '{print $5}') screen_id=$(xprop -id "$active_win" _NET_WM_SCREEN | awk '{print $NF}') xrandr | awk -v id="$screen_id" '/ connected/ {if (NR-1 == id) print $1}'
内容的提问来源于stack exchange,提问作者Jakob Guldberg Aaes
相关产品推荐
相关产品推荐

