我有一个命令(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)
这<()
是 shell 提供的语法bash
,它在内部运行命令并使命令的输出就像出现在文件中一样。作为第二个文件内容,我们使输出logcat
出现在那里。所以awk
尝试从两个输入流中读取。
当我们一次从多个输入流读取时使用的逻辑。FNR==NR
和是特殊变量,用于跟踪每个文件和整个输入流的行号。因此,对于条件,我们基本上定义了在第一个文件上运行的后面的操作,以及在第二个文件上运行的后面的操作。awk
FNR
NR
FNR==NR
{..}
所以在第一文件像流一样,我们看到输出,PKG_PID_LIST
从中创建一个哈希映射,其中键为进程 ID,进程名称为值。一旦我们处理完这个文件,我们就已经将所有 PID 与其名称进行了映射。
在第二个文件中,我们使用此映射$3 in pidMap
含义,第二个流中的值$3
作为我们刚刚处理的键存在,我们将$3
第二个流($3
第三个空格分隔列)上的值更新为键的映射值。这{..}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_
为等于您的 shell 变量PKG_PID_LIST
。 - 对于 读取的输入的第一行,使用键作为第二个字段和值作为第一个字段来
perl
初始化哈希。%h
- 现在只需找到当前行中的第三个字段 ,
/(?:\H+\h+){2}\K(\H+)/
并将其替换为相应的哈希条目 ,即可$h{$1}
。