删除最后出现的模式行

Remove the last-occured lines of patterns

我想 exclude/delete 模式 {n}{n}{n}.log 的最后一行,用于每个可能的 3 位数字。每行以示例模式“123.log”结束。

示例输入文件:

aaaa116.log
a112.log
aaa112.log
a113.log
aaaaa112.log
aaa113.log
aa112.log
aaa116.log
a113.log
aaaaa116.log
aaa113.log
aa114.log

输出文件:

aaaa116.log
a112.log
aaa112.log
a113.log
aaaaa112.log
aaa113.log
aaa116.log
a113.log

bash 脚本如何执行此操作?

awk 可能是最简单的工具。比如这个单行

tac file | awk 'match([=10=], /[0-9]{3}.log/,a) && a[0] in b; {b[a[0]]}' | tac

为示例输入生成请求的输出。这不需要将整个文件存储在内存中。

更改正则表达式以满足您的特定需求。

在不保留顺序的情况下删除 awk 中的最后一个匹配行非常简单。

awk -F'[^0-9]+' '/[0-9]+\.log$/ {
    t = $(NF - 1);
    if (t in a)
        print a[t];
    a[t] = [=10=];
}'

保持输出有序比较复杂,需要更多内存。

awk -F'[^0-9]+' '/[0-9]+\.log$/ {
    t = $(NF - 1);
    a[++i] = [=11=];
    b[[=11=]] = t;
    c[t] = i;
}
END {
    for (n = 1; n <= i; n++)
        if (n != c[b[a[n]]])
            print a[n];
}'

要通过第一个示例中的非匹配行,可以将 next 语句添加到操作中,并可以附加 1 的模式。对于第二个示例,数组 a 中的赋值可以移动到它自己的操作中。

$ awk '{k=substr([=10=],length()-7)} NR==FNR{n[k]=NR;next} FNR!=n[k]' file file
aaaa116.log
a112.log
aaa112.log
a113.log
aaaaa112.log
aaa113.log
aaa116.log
a113.log