如何在行中附加数字后缀以删除重复项?
伪代码:
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
笔记:
- 最终副本必须保持不变。
- 早期的重复项可以具有任何唯一的后缀,因此我选择了倒计时。
- 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