我有一个大文件(线程转储)。我有一堆已命名的线程my-thread-\d+
,如果它们正在等待,我想从文件中删除该行和接下来的 20 行。
例如,我可能有一行看起来像:
"my-thread-1" #628 prio=5 os_prio=0 cpu=54888.61ms elapsed=194386.85s allocated=80325M defined_classes=4 tid=0x00007f406000c9d0 nid=0xb873 waiting on condition [0x00007f3faaeed000]
接下来是 20 行我不想要的行。
该模式将在文件中多次出现。我想对文件运行一个命令,每次删除 20 行my-thread-
后跟waiting on conditon
.
答案1
和awk
:
awk '/my-thread-[[:digit:]]/ && /waiting on condition/ {skip = 21}
skip-- <= 0'
如果在跳过的行内出现另一个等待线程,skip
则重置为 21 并从那里再次跳过 21 行。
使用pcregrep
(但忽略跳过行内进一步等待的线程):
pcregrep -Mv 'my-thread-\d.*waiting on condition(.*\n){20}'
答案2
在这种情况下,该grep
实用程序几乎毫无用处,因为无法根据前一行的匹配来排除行(-A
在 的某些实现中对可用选项的意义进行了某种否定grep
)。
我将该请求解释为想要跳过匹配行和另外 20 行,而不查看这 20 行以查看模式是否再次匹配。
使用一种简单的方法sed
是,每当输入中出现触发模式时,将以下 20 行附加到编辑缓冲区,然后将其全部删除。
sed '/^"my-thread-[[:digit:]]\{1,\}".*waiting on conditon/ { N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;N;d; }' file
我们可以对awk
.
awk '/^"my-thread-[[:digit:]]+".*waiting on conditon/ { for (i=0; i<20; ++i) getline; next }; 1' file
或者,既然awk
知道它在哪一行,我们可以向前跳过 20 行。
awk 'FNR < skip_to { next } /^"my-thread-[[:digit:]]+".*waiting on conditon/ { skip_to = FNR+21; next }; 1' file
在上面的代码中,FNR
是包含当前文件中行号的特殊变量,而skip_to
是当触发模式匹配时我们要跳到的行号。
答案3
awk '/my-thread-.*waiting on condition/{c=21} !(c&&c--)' file
例如:
$ seq 20 | awk '/3/{c=6} !(c&&c--)'
1
2
9
10
11
12
19
20
$ seq 20 | awk '/3/{c=11} !(c&&c--)'
1
2
看使用 sed-或 awk-a-line-follow-a-matching-pattern 进行打印了解详细信息和其他相关习语。