Bash は文字列をコマンドに置き換えます。

Bash は文字列をコマンドに置き換えます。

次のような長いログを出力するコマンド(logcat)があります。

07-27 09:26:22.416 17574 17886 D SurfaceControl: Excessive delay in setPowerMode()
07-27 09:26:22.421 17574 17599 I PowerManagerService: Sleeping (uid 1000)...
07-27 09:26:22.427 17489 17527 D audio_hw_primary: adev_set_parameters: enter: screen_state=off

形式は次のとおりです。[Date] [Time] [Process ID] [Thread ID] [Log Type] [Text]

プロセスIDではなくプロセス名(より正確にはパッケージ)を見たいです。

パッケージ名は、以下を使用してプロセスIDで取得できます。

echo "$PKG_PID_LIST" | grep -w $PID | cut -d ' ' -f1

たとえば、

$ echo "$PKG_PID_LIST" | grep -w 17489 | cut -d ' ' -f1
org.lineageos.audiofx

気になる場合ははい、私はAndroidを使用しており、次のようにリストを作成しています。

PKG_PID_LIST=$(eval $(pm list packages | cut -d ':' -f 2 | sed 's/^\(.*\)$/echo \"\$\(echo \1\) \$\(pidof \1\)\";/'))

最終出力は次のようになります。

07-27 09:26:22.416 com.android.systemui 17886 D SurfaceControl: Excessive delay in setPowerMode()
07-27 09:26:22.421 com.android.systemui 17599 I PowerManagerService: Sleeping (uid 1000)...
07-27 09:26:22.427 org.lineageos.audiofx 17527 D audio_hw_primary: adev_set_parameters: enter: screen_state=off

編集:$ PKG_PID_LISTの出力例:

$ echo "$PKG_PID_LIST"
com.android.deskclock 18937
com.android.systemui 17574
net.osmand.srtmPlugin.paid 
com.android.bluetoothmidiservice 
org.lineageos.audiofx 17489

(実行されていないパッケージにはPIDはありません。パッケージ名の後には常にスペースがあります。)

答え1

複数の入力ソースから読み込み、必要に応じてカスタムアクションを適用しますawk

awk 'FNR==NR{pidMap[$2]=$1; next}$3 in pidMap{$3=pidMap[$3]}1' <(echo "$PKG_PID_LIST") <(logcat)

これは、内部的にコマンドを実行し、コマンドの出力をファイルに表示されているかのように表示する<()シェルによって提供される構文です。bash2番目のファイルの内容として、出力がlogcatここに表示されるようにします。だからawk 努力する2 つの入力ストリームから読み込みます。

複数の入力ストリームを同時に読み取るときに使用されるロジックです。FNR==NR各ファイルの行番号と入力ストリーム全体を追跡するために使用される特殊変数です。したがって、条件の場合、デフォルトでは、最初のファイルで実行される次のタスクと、2番目のファイルで実行される次のタスクを定義します。awkFNRNRFNR==NR{..}

だから最初は文書ストリームと同様に、出力を表示し、PKG_PID_LISTキーがプロセスIDでプロセス名が値であるハッシュマップを生成します。このファイルを処理した後、すべてのPIDをその名前にマップしました。

2番目のファイルはこのマップセマンティクスを$3 in pidMap使用します。 2番目のストリームの値は処理$3したばかりのキーとして存在し、$32番目のストリーム($33番目のスペースで区切られた列)の値をキー値のマップに更新します。 。これは、変更に基づいて行を再作成するように指示する{..}1アクションですawk(または、変更がない場合は行を印刷します)。


logcat継続的に出力を生成し、出力が決定された後にこのコマンドを実行する場合は、まず出力を一時ファイルに書き込んでから渡すことをお勧めします。それawk.

答え2

次のことができます。

logcat |\
_PKG4PID_="$PKG_PID_LIST" \
perl -lpe '
    %h = reverse split /\s+/, $ENV{_PKG4PID_} if $. == 1;
    s/(?:\H+\h+){2}\K(\H+)/$h{$1}/;
' 

説明する:

  • 環境変数を_PKG4PID_シェル変数と同じに設定しますPKG_PID_LIST
  • 入力読み出しの最初の行では、perlキーを2番目のフィールドとして使用し、値を1番目のフィールドとして使用してハッシュを初期化します。%h
  • 次に、現在の行で3番目のフィールドを見つけて、対応する/(?:\H+\h+){2}\K(\H+)/ハッシュ項目に置き換えます$h{$1}

関連情報