You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 22:47:32