通过添加数字后缀删除重复项

通过添加数字后缀删除重复项

如何在行中附加数字后缀以删除重复项?

伪代码:

if currLine.startsWith("tag:")
  x = numFutureLinesMatching(currLine)
  if (x > 0)
    currLine = currLine + ${x:01}

输入文件

tag:20230901-FAT
val:1034
tag:20230901-FAT
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500

所需输出

tag:20230901-FAT-02
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX-01
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500

笔记:

  1. 最终副本必须保持不变。
  2. 早期的重复项可以具有任何唯一的后缀,因此我选择了倒计时。
  3. awk 似乎是一个不错的选择,但任何常见的脚本语言都可以。

答案1

awk可以采用任意数组索引 - 甚至是整个记录(“行”)。

进行正则表达式匹配tag:并启动计数器,但由于第一个匹配而纠正一个

awk '$0 ~ /^tag:/ { n[$0]++?$0=sprintf("%s-%02d",$0,n[$0]-1):1 }  1'

要使其成为倒计时,请使用tac两次:

tac infile | 
awk '$0 ~ /^tag:/ { n[$0]++?$0=sprintf("%s-%02d",$0,n[$0]-1):1 }  1' |
tac

答案2

我们开始吧,完全按照要求:

awk '
    NR==FNR{
        if (/^tag:/) {
            a[$1]++
        }
        next
    }
    {
        c=--a[$1]
        if (c>0) {
            printf "%s-%.2d\n", $1, c
        } else {
            print
        }
    }
' file file

附有解释:

awk '
    # first block for first file
    NR==FNR{                           # first file
        if (/^tag:/)                   # if the line starts with ^tag:
            a[$1]++                    # increment array a with key as column 1
        next                           # stop processing this line
    }                                                                   
    # 2th block for second file
    {
        c=--a[$1]                      # c = decrement array a with key as column 1
        if (c>0) {                     # ... pretty simple, no ?
            printf "%s-%.2d\n", $1, c  # %s = string %.2d integer, zero pading
        } else {                 
            print                      # else, print current line
        }
    }                                         
' file file 

输出

tag:20230901-FAT-02
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX-01
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500

答案3

:

#!/usr/bin/perl

use strict; use warnings;
use feature qw/say/;

my (%h, $c);
while (<>) {
    chomp;
    if (/^tag:/) {
        $c = sprintf "%.2d", ++$h{$_};
        if ($c>1) {
            say $_ . "-" . $c;
        } else {
            say;
        }
    } else {
        say $_;
    }
}

用法:

./script file

输出:

tag:20230901-FAT
val:1034
tag:20230901-FAT-02
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX-02
val:1000
tag:20230901-FAT-03
val:1500

答案4

使用(以前称为 Perl_6)

~$ raku -ne 'BEGIN my %hash; put /^tag\:/ && %hash{$_}++ ?? $_ ~ sprintf("-%02d", %hash{$_}-1) !! $_;'   file

awk以上是@EdMorton 在评论中发布的优秀答案的 Raku 版本。

首先在命令行中使用-ne非自动打印逐行标志调用 Raku。在BEGIN通过声明%hash.put对输入运行... 语句。如果该行/^tag:/以 开头,则tag:将该行添加到%hash++增加其值。

这个&&条件构成了 Raku 的“测试 ?? 真的 !! 错误的" 三元运算符。如果为 True,则该$_行输出时put附加该行的值减一(使用 解码的值%hash{$_})。如果为 False,则该行不改变地输出put

输入示例:

tag:20230901-FAT
val:1034
tag:20230901-FAT
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500

示例输出:

tag:20230901-FAT
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX-01
val:1000
tag:20230901-FAT-02
val:1500

上面实现了一个计数后缀,保持最早的tag:行不变。要实现使最后几行保持不变的倒计时后缀tag:,请tac按照 @FelixJN 接受的答案中的指示使用两次。下面是在 MacOS 上实现的答案,它使用tail -r而不是tac

~$ tail -r  Steve_suffix.txt | raku -ne 'BEGIN my %hash; put /^tag:/ && %hash{$_}++ ?? $_ ~ sprintf("-%02d", %hash{$_}-1) !! $_;' | tail -r
tag:20230901-FAT-02
val:1034
tag:20230901-FAT-01
val:1500
tag:20230901-LAX-01
val:8934
tag:20230901-SMF
val:2954
tag:20230901-LAX
val:1000
tag:20230901-FAT
val:1500

https://unix.stackexchange.com/a/114043
https://docs.raku.org/language/operators#infix_??_!
https://raku.org

相关内容