Получение только имени приложения из wmctrl -l

До сих пор я только что добавил строку nameserver 8.8.8.8 в мой /etc/resolv.conf перед всеми другими строками сервера имен, и это устранило проблему. Я все еще обеспокоен тем, что это изменение будет перезаписано NetworkManager

2
04.02.2017, 13:34
5 ответов

Есть несколько способов сделать это. В зависимости от предпочитаемого типа инструмента вы можете выбрать один из них

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? Флаг -f , очевидно, должен знать диапазон, поэтому с вводом, который имеет произвольное количество слов в строке, мы, очевидно, не можем знать диапазон, но мы можем использовать что-то достаточно большое, отсюда 9999.

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

Perl

Мы можем воспользоваться режимом автоматического разделения -a , в котором слова каждой строки, прочитанной из stdin, разбиваются на массив. Это потенциально можно улучшить и сократить.

$ 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])"

В качестве альтернативы мы можем использовать короткий сценарий для имитации разреза вместо однострочного. Это будет работать намного лучше для многострочного текста / ввода и намного более читабельно

#!/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

Этот способ использует преимущества регулярных выражений. Мы сопоставляем строку от начала строки ^ до границы слова попугай с помощью \ b и следующего пробела и удаляем их (фактически устанавливая нулевую строку)

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

В качестве альтернативы, чтобы избежать жадного сопоставления, мы можем использовать следующее:

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

Шаблон не слишком сложный. Мы начинаем сопоставление в начале строки и сопоставляем любое количество символов (часть * ) которые не являются пробелами (часть [^] ) три раза разделены любым количеством пробелов. Таким образом, ^ [^] * соответствует первому слову, * соответствует любому количеству пробелов, второе [^] * соответствует второму слову, а второе * соответствует второму пробелу, наконец, [^] * соответствует третьему слову плюс пробел.

BASH + xargs

Мы можем воспользоваться возможностью bash перебирать аргументы командной строки и передавать каждую строку (-L 1) как набор аргументов командной строки в bash -c '' .Остальное просто - мы избавляемся от первых трех аргументов и печатаем остальные

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

В качестве альтернативы, как предложил Стефан Чазелас в комментариях: при условии, что из wmctrl -l передаются как минимум 3 позиционных аргумента. (что в данном случае должно быть верным), решение можно сократить до:

wmctrl -l | xargs -L 1 bash -c 'shift 3;printf "%s " "$@";printf "\n"' sh
2
27.01.2020, 22:03

Вы можете использовать:

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

, который не будет считать «-» в «-1» для закрепленных окон в качестве столбца.

0
27.01.2020, 22:03

Вы можете обрезать вывод фиксированной ширины с помощью wmctrl -l | вырезать -c15-

0
27.01.2020, 22:03

Вы можете использовать cut , поскольку wmctrl (правильно) не имеет параметров фильтрации. Вероятно, это это то, что вы хотите:

wmctrl -l | cut -d ' ' -f 4-
1
27.01.2020, 22:03
sed -n 's/.* parrot //p'

Будет печатать то, что находится справа от крайнего правого появления "parrot" в строках, содержащих «попугай» . Это потому, что . * выше является жадным и будет соответствовать как можно большему количеству совпадений.

В вашем случае это будет проблемой для вывода, например:

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

Если вы хотите напечатать то, что находится справа от крайнего левого вхождения "parrot" , a общий трюк:

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

То есть мы заменяем первое (крайнее левое) вхождение "parrot" новой строкой (символ, который иначе никогда не будет найден в пространстве шаблонов). А затем удалите все до этой новой строки (которая гарантированно будет уникальной).

Однако здесь похоже, что вам нужны заголовки окон из клиента parrot , поэтому строки from, где третье поле - parrot , так:

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

Или with 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 , чтобы определить, где записи начало и конец. Это не будет полностью надежным (как в случае, если кто-то делает xterm -n $ 'foo \ n0x0 0 parrot something' ), но должно быть нормально, когда вы не сталкиваетесь с злонамеренными пользователями.

1
27.01.2020, 22:03

Теги

Похожие вопросы