获取每行的最后一个单词

gee*_*eek 3 linux awk text-processing regular-expression

我有一个由 strace 生成的大文本文件,其中简要包含:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 42.93    3.095527         247     12512           unshare
 19.64    1.416000        2975       476           access
 13.65    0.984000        3046       323           lstat
 12.09    0.871552         389      2239       330 futex
 11.47    0.827229          77     10680           epoll_wait
  0.08    0.005779          66        88           fadvise64
  0.06    0.004253           4      1043       193 read
  0.06    0.004000           3      1529         3 lstat
  0.00    0.000344           0      2254      1761 stat
[...]
  0.00    0.000000           0         1           fallocate
  0.00    0.000000           0        24           access
  0.00    0.000000           0         1           open
Run Code Online (Sandbox Code Playgroud)

不包括第一个标题行,我想从每一行获取最后一个字段,对应于系统调用列。这些包括:

  • 取消共享
  • 使用权
  • 统计数据
  • 富泰克斯
  • epoll_等待
  • ..
  • ...

这是我尝试过的 tail -n -13 seccomp | awk '{print $5}',它能够忽略第一行,但由于我的搜索没有细化,某些包含错误行的行被忽略。

我如何实现这个?

Rud*_*diC 13

或者像这样:

\n
awk 'NR>2 {print $NF}' seccomp\nunshare\naccess\n.\n.\n.\n
Run Code Online (Sandbox Code Playgroud)\n

对于第二行之后的行,打印该行的最后一个字段。NF保存字段数,$NF“扩展”到最后一个字段的内容\xc2\xb9。

\n
\n

\xc2\xb9 或整个记录(如果不包含任何字段)(仅由空格组成FS,默认值为 字段分隔符)。

\n


小智 10

您可以轻松地使用grep选项-o(缩写形式--only-matching)。

grep -o "\w*$" filename
Run Code Online (Sandbox Code Playgroud)
  • \w匹配任何单词字符(字母数字和下划线)
  • \w*匹配多个(包括零个)单词字符
  • \w*$匹配行尾的多个单词字符

要跳过标题,请tail -n +3按照其他人的建议使用:

tail -n +3 filename | grep -o "\w*$"
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

unshare
access
lstat
futex
epoll_wait
fadvise64
read
lstat
stat
fallocate
access
open
Run Code Online (Sandbox Code Playgroud)


Phi*_*pos 9

有了sed它就简单了

sed '1,2d;s/.* //'
Run Code Online (Sandbox Code Playgroud)
  • 1,2d意思是d删除第一行到第二行,替换tail
  • ubstitute命令s删除最后一个空格之前的所有内容,因此您不需要计算列数

据我所知,系统调用不能包含任何空格,所以这应该可行。否则,您可以依赖从第 61 个字符开始的名称,删除前 60 个字符:

sed '1,2d;s/.\{60\}//'
Run Code Online (Sandbox Code Playgroud)


Ste*_*mit 6

打印一行中最后一个字段的标准习惯用法是

awk '{print $NF}'
Run Code Online (Sandbox Code Playgroud)

NF变量会自动设置为该行的字段,然后提取该字段。$

我想说,摆脱不需要的标题行的最简单、最安全的方法是使用egrep.

把这些放在一起我们有:

scs$ awk '{print $NF}' seccomp | egrep -v '^(--*|syscall)$'
Run Code Online (Sandbox Code Playgroud)

(这会错误地排除名为“syscall”的实际系统调用。想必这应该不是问题。)