从 wmctrl -l 中仅获取应用程序名称

从 wmctrl -l 中仅获取应用程序名称

我试图从这段代码中获取应用程序名称:

wmctrl -l

但我不知道该怎么做!

如果您能解释一下我如何做到这一点,那就太好了。

编辑:

的输出wmctrl -l是:

0x01000007 -1 parrot Top Expanded Edge Panel
0x01000017 -1 parrot Bottom Expanded Edge Panel
0x01200006 -1 parrot x-caja-desktop
0x03600006  0 parrot Terminal
0x03000130  0 parrot scripting - Getting a string after a word in BASH - Unix & Linux Stack Exchange - Google Chrome

所以我需要之后的一切parrot

答案1

有几种方法可以做到这一点。根据您喜欢的工具类型,您可以选择一种工具

AWK

最合适的方式。将单词 1,2,3 设置为空字符串并打印

$ wmctrl -l | awk '{$1=$2=$3="";print}'  

或者,要消除前导空格,您可以执行以下操作:

$ wmctrl -l | awk '{for(i=4;i<=NF;i++) printf "%s ",$i;print ""}'

有点尴尬的方法,我们打印特定字段之后的所有内容,直到字段 9999。为什么是 9999 ?-fflag 显然需要知道范围,因此对于每行具有任意数量单词的输入,我们显然无法知道范围,但我们可以使用足够大的东西,因此 9999。

$ wmctrl -l | cut -d " " -f 5-9999

珀尔

我们可以利用-a自动分割模式,将从标准输入读取的每一行的字分割成数组。这可能会得到改进和缩短。

$ wmctrl  -l | perl -lane 'my $numels=scalar @F;print @F[3..$numels]'

Python

有点长但有效。 Python 没有像 perl 那样的自动分割模式,但我们可以在读取每个字符串时手动执行此操作。

$ wmctrl -l | python -c "import sys; print '\n'.join([' '.join(line.split()[3:]) for line in sys.stdin])"

或者,我们可以使用一个简短的脚本来模拟cut,而不是单行脚本。这对于多行文本/输入会更好,并且更具可读性

#!/usr/bin/env python
import sys

start=int(sys.argv[1])
for line in sys.stdin:
    print " ".join(line.strip().split()[start:])

并这样称呼它:

$ wmctrl -l | ./print_words.py 3

SED

这种方式利用了正则表达式。我们从行首^到单词边界匹配字符串parrot以及\b后面的空格,然后删除它们(有效设置为空字符串)

$ wmctrl -l | sed 's/^.*\bparrot\ //'

另外,为了避免贪婪匹配,我们可以使用以下方法:

$ wmctrl -l | sed 's/^[^ ]* *[^ ]* *[^ ]* //'

模式并不太复杂。我们从行首开始匹配,将任意数量的*非空格(部分)的字符([^ ]部分)匹配三遍,并以任意数量的空格分隔。因此 ^[^ ]*匹配第一个单词,*匹配任意数量的空格,第二个[^ ]*匹配第二个单词,第二个*匹配第二个空格,最后[^ ]*匹配第三个单词加空格。

BASH + xargs

我们可以利用 bash 迭代命令行参数的能力,并将每一行 ( -L 1 ) 作为一组命令行参数传递给bash -c ' '.剩下的很简单 - 我们去掉前 3 个参数,然后打印剩下的

wmctrl -l | xargs -L 1 bash -c 'for i in 1 2 3;do shift ; done ; printf "%s " "$@";printf "\n"' sh

或者,正如 Stephane Chazelas 在评论中所建议的:只要至少有 3 个位置参数被传递wmctrl -l(在这种情况下应该始终为真),解决方案可以缩短为:

wmctrl -l | xargs -L 1 bash -c 'shift 3;printf "%s " "$@";printf "\n"' sh

答案2

您可以使用作为控制面板(正确地)缺乏过滤选项。可能这就是您想要的:

wmctrl -l | cut -d ' ' -f 4-

答案3

sed -n 's/.* parrot //p'

将打印右侧的内容最右边的出现" parrot "在包含 的行上" parrot "。这是因为.*上面是贪婪的,并且会尽可能匹配。

在你的情况下,这将是一个输出问题,如:

0x03a00003  0 parrot parrot (~) (1 of 2) - GVIM

如果你想打印右边的内容最左边发生时" parrot ",一个常见的技巧是:

sed -n '/ parrot /{
  s//\
/; s/.*/\n/p
}'

也就是说,我们" parrot "用换行符(否则永远不会在模式空间中找到的字符)替换第一个(最左边)出现的 。然后删除换行符之前的所有内容(保证是唯一的)。

不过,在这里,您似乎想要从parrot客户端获得窗口的标题,因此第三个字段所在的行parrot,因此:

sed -n 's/^[^ ]\{1,\} \{1,\}[^ ]\{1,\} \{1,\}parrot //p'

或者与perl

perl -ne 'print if s/^\H+\h+\H+\h+parrot //'

请注意,我们假设窗口标题不包含换行符,这通常是这种情况,但不能保证。例如尝试之后:

xterm -n $'foo\nbar'

如果你想解释这一点,你可以这样做:

perl -0777 -ne '$prefix = qr{0x[\da-f]+\h+-?\d+\h+};
                print for /^${prefix}parrot (.*?\n)(?=$prefix|$)/gms'

即使用所有条目开头的事实来0x<hex> <dec>标识记录的开始和结束位置。这并不是完全万无一失的(就像有人这样做的情况一样xterm -n $'foo\n0x0 0 parrot something'),但在不面对恶意用户时应该没问题。

答案4

您可以修剪固定宽度输出 wmctrl -l | cut -c15-

相关内容