web-dev-qa-db-ja.com

psコマンドからキーと値のペアを抽出する方法

次のようにpsコマンドからアプリケーション名を抽出しようとしています:

ps -af -u sas |grep "Java"| grep -v "grep"

そしてそれは以下を生成します:

sas 24431     1  0 Oct10 ?        00:51:08 /usr/lib/jvm/Java-1.7.0-Oracle-1.7.0.25.x86_64/jre/bin/Java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/Java/logs

egrepを使用してみましたが、機能していないようです。

ps -af -u sas|grep "Java"| grep -v "grep"| egrep -o "-Dapp.name"

-Dapp.name値「myApp」のみを取得するにはどうすればよいですか?

10
Sas

awkの場合:

ps -af -u sas | awk 'BEGIN {RS=" "}; /-Dapp.name/'
7
jasonwryan

表示されているエラーメッセージは表示されていませんが、おそらく

grep:不明なデバイスのメソッド

これは、他のすべてのコマンドラインプログラムと同様に、grep-で始まるものはすべてオプションであると想定し、そのように解析しようとするためです。この場合、-Dを使用して、grepにデバイスファイルの処理方法を指示します(詳細については、man grepを参照してください)。これを回避する1つの方法は、--を使用することです。これはgrepに、後続のすべてがオプションフラグではないことを伝えます。

これをGNU grepのPCRE機能と組み合わせると、次のことができます。

ps -af -u sas | grep -v grep | grep -Po -- '*-\KDapp.name=[^\s]+'

正規表現は-を検索して破棄し(\K)、次に文字列Dapp.name=に続けて可能な限り多くの非スペース文字を続けます。出力は次のとおりです。

Dapp.name=myApp

myAppの部分を変数に保存したい場合は、それだけを検索します。

ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+'

変数に割り当てるには:

$ app="$(ps -af -u sas | grep -v grep | grep -Po -- '-Dapp.name=\K[^\s]+')"
$ echo $app
myApp

ただし、このような場合にはgrepの出力をpsにしないでください。これが pgrep の目的です。

app="$(pgrep -a Java | grep -Po -- '^Dapp.name=\K[^\s]+')"
8
terdon
ps -af -u sas | sed -n '/[j]ava/s/.*-Dapp\.name=\([^ ]*\).*/\1/p'
4
Barmar

他の回答よりも複雑ですが、これはgetoptを使用して解析を処理します。さらに別の選択肢。

_getopt -aql 'Dapp.name:' $(\
    ps -af -u sas | grep Java | grep -v grep | tr -s ' ' | cut -d' ' -f8-\
) | cut -d"'" -f2
_
  1. あなたのコマンド:_ps -af -u sas | grep Java | grep -v grep_
  2. _tr -s ' '_ cutの準備として、複数のスペースを1つのスペースに「圧縮」します
  3. _cut -d' ' -f8-_は行をスペースで分割し、8を含むすべてのフィールドを取得します。結果は_/usr/lib/jvm/Java-1.7.0-Oracle-1.7.0.25.x86_64/jre/bin/Java -Denv=DEV -Dapp.name=myApp -Xms512m -Xmx1g -Dlog.dir=/apps/Java/logs_です。
  4. getopts -aql 'Dapp.name:' $(...)は、コマンドオプションを解析し、値が_Dapp.name_である_:_に一致するロングネームのみを出力します。結果は_--Dapp.name 'myApp' --_です。
  5. _cut -d"'" -f2_は一重引用符で囲まれています
  6. 結果は次のとおりです:myApp
3
zamnuts

ps … | grep …を使用していて、結果からgrepを除外する必要があるときはいつでも、間違っています。

psの出力を解析する0番目のルールは、pgrepなどのより信頼できるツールを使用することです。 pgrepがある場合、pgrep -f JavaはコマンドJavaを実行しているすべてのプロセスをリストします。オプション-lは、各プロセスのコマンドラインを追加します。

-Dapp.nameへの引数を抽出するには、sedを使用できます。行全体を一致させ、グループの興味深い部分を詰めて配置し、そのグループを印刷します。

pgrep -lf Java | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'

psの出力を解析する最初の規則は、_-oオプションを使用して必要なフィールドを選択することです。ここでは、コマンド引数のみに関心があるので、それだけを出力します。

ps -e -o args= | sed -n 's/^.*-Dapp\.name=\([^ ]*\).*$/\1/p'

私はpgrepの代わりにpsを使用するでしょう:

$ pgrep -fa Java | grep -op "(<=-Dapp.name=)\w+"

これにより、Javaに一致するすべてのプロセスが返され、-Dapp.name=を含むプロセスのみが表示されます。最後のビット\w+は、スペースが含まれていないと仮定して、プログラム名を示します。

注:-Pgrepに切り替えると、 PCRE-Perl互換レギュラーを使用して物を指定する機能が追加されます式grepのすべてのバージョンでサポートされているわけではありませんが、最新バージョンのLinuxにはほとんどのバージョンが含まれています。

キー/値の出力全体が必要な場合は、次のように変更します。

$ pgrep -fa Java | grep -oP -- "-Dapp.name=\w+"
0
slm