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?-fフラグは明らかに範囲を知る必要があるため、1行に複数の単語を含む入力の場合は明らかに範囲がわかりませんが、十分に大きいものを使用できるため、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または、1行のスクリプトではなく短いスクリプトを使用してシミュレーションすることもできます。複数行のテキスト/入力に適しており、読みやすくなります。

#!/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/^[^ ]* *[^ ]* *[^ ]* //'

パターンはそれほど複雑ではありません。行の先頭から始めて、空白ではなく*文字(parts [^ ])を必要な数のスペースで区切って3回一致させます。したがって ^[^ ]*、最初の単語と一致し、*スペースの数と一致し、2番目の単語が[^ ]*2番目の単語と一致し、2番目の単語が*2番目のスペースと一致し、最後に3[^ ]*番目の単語とスペースが一致します。

BASH + xargs

コマンドライン引数を繰り返し、各行(-L 1)をコマンドライン引数のセットに渡すbashの機能を利用できます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ただし、ここではクライアントからウィンドウのタイトルを取得したいと思うので、3番目のフィールドがある行は次のようになります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-

関連情報