Obtendo apenas o nome do aplicativo de wmctrl -l

2

Estou tentando apenas obter o nome do aplicativo desse código:

wmctrl -l

mas não sei como fazer isso!

Se você pudesse explicar como eu poderia fazer isso, seria ótimo.

EDITAR:

A saída de 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

então preciso de tudo depois de parrot

    
por MaliciouZzHD 04.02.2017 / 03:43

5 respostas

1

Existem várias maneiras de fazer isso. Dependendo do seu tipo de ferramenta preferido, você pode escolher um sobre outro

AWK

A maneira mais apropriada. Definir palavras 1,2,3 para seqüência vazia e imprimir

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

Como alternativa para se livrar do espaço principal, você pode fazer isso:

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

corte

Uma aproximação um pouco desajeitada, nós imprimimos tudo depois de um campo específico até o campo 9999. Por que 9999? -f flag aparentemente precisa saber range, então com input que tem um número arbitrário de palavras por linha, nós obviamente não podemos saber o range, mas podemos usar algo suficientemente grande, daí 9999.

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

Perl

Podemos aproveitar o modo -a autosplit, em que palavras de cada linha lidas de stdin são divididas em array. Isso potencialmente poderia ser melhorado e encurtado.

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

Python

Um pouco longo mas funciona. O Python não tem o modo de divisão automática como perl, mas podemos fazer isso manualmente em cada string.

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

Como alternativa, podemos usar um script curto para simular o cut , em vez do one-liner. Isso funcionaria muito melhor para textos / entradas multilinhas e é muito mais legível

#!/usr/bin/env python
import sys

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

E chame da seguinte forma:

$ wmctrl -l | ./print_words.py 3

SED

Desta forma, aproveita as expressões regulares. Nós combinamos a string desde o começo da linha ^ até o limite da palavra parrot com \b e após o espaço, e os deletamos (efetivamente configurando a string nula)

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

Como alternativa, para evitar a correspondência gananciosa, podemos usar o seguinte:

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

O padrão não é muito complexo. Iniciamos a correspondência no início da linha e combinamos qualquer número de caracteres (a * part) que não são espaço ( [^ ] part) três vezes separados por qualquer número de espaços. Portanto, ^[^ ]* corresponde à primeira palavra, * corresponde a qualquer número de espaços, segundo [^ ]* corresponde à segunda palavra e segundo * corresponde ao segundo espaço, finalmente com [^ ]* correspondendo à terceira palavra mais espaço.

BASH + xargs

Podemos aproveitar a capacidade do bash para iterar sobre argumentos de linha de comando e passar cada linha (-L 1) como um conjunto de argumentos de linha de comando para bash -c ' ' . O resto é simples - obtemos os primeiros 3 argumentos e imprimimos o resto

wmctrl -l | xargs -L 1 bash -c 'for i in 1 2 3;do shift ; done ; printf "%s " "$@";printf "\n"' sh
Alternativamente, como sugerido por Stephane Chazelas nos comentários: enquanto houver pelo menos três argumentos posicionais sendo passados de wmctrl -l (que neste caso deve ser consistentemente verdadeiro), a solução pode ser reduzida para:

wmctrl -l | xargs -L 1 bash -c 'shift 3;printf "%s " "$@";printf "\n"' sh
    
por 04.02.2017 / 04:12
1

Você pode usar recortado como wmctrl (corretamente) não possui opções de filtragem. Provavelmente é isso que você quer:

wmctrl -l | cut -d ' ' -f 4-
    
por 04.02.2017 / 03:52
1
sed -n 's/.* parrot //p'

Imprimiria o que está à direita da ocorrência mais à direita de " parrot " nas linhas que contêm " parrot " . Isso porque o .* acima é ganancioso e corresponderá o máximo possível.

No seu caso, isso seria um problema para a saída como:

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

Se você quiser imprimir o que está à direita da ocorrência mais à esquerda de " parrot " , um truque comum é:

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

Ou seja, substituímos a primeira ocorrência (mais à esquerda) de " parrot " por nova linha (um caractere que nunca seria encontrado no espaço padrão). E, em seguida, remova tudo até a nova linha (que é garantida como única).

Aqui, parece que você quer o título das janelas do parrot client, então as linhas de onde o terceiro campo é parrot , então:

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

Ou com perl :

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

Note que estamos assumindo que os títulos das janelas não contêm caracteres de nova linha, o que geralmente é o caso, mas não garantido. Tente por exemplo depois:

xterm -n $'foo\nbar'

Se você quisesse explicar isso, poderia fazer isso:

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

Isso é usado pelo fato de que todas as entradas começam com 0x<hex> <dec> para identificar onde os registros começam e terminam. Isso não seria completamente infalível (como no caso de alguém fazendo xterm -n $'foo\n0x0 0 parrot something' ), mas deveria estar OK quando não estivesse diante de usuários maliciosos.

    
por 04.02.2017 / 10:53
0

Você pode usar:

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

que não contará o "-" em "-1" para janelas fixas como uma coluna.

    
por 04.02.2017 / 04:03
0

Você pode cortar a saída de largura fixa com wmctrl -l | cut -c15-

    
por 04.02.2017 / 09:37