重複を排除するために行に数字のサフィックスを追加するには?
擬似コード:
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:
カウンタを開始しますが、最初の一致のために1つを修正します。
awk '$0 ~ /^tag:/ { n[$0]++?$0=sprintf("%s-%02d",$0,n[$0]-1):1 } 1'
カウントダウンにするにはtac
2回使用してください。
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
まず、自動印刷ではなく1行ずつフラグを使用してコマンドラインからRakuを呼び出します。BEGIN
文を介した入力時に文を実行します%hash
。put
行が/^tag:/
次から始まる場合は、tag:
行を追加して%hash
その++
値を増やします。
この&&
条件が楽の「テスト ??
本物 !!
間違った三項演算子。Trueの場合、行から1を引いた値が追加された$_
行が出力されます(デコードされた値を使用)。Falseの場合、行は変更されずに出力されます。put
%hash{$_}
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:
@FelixJNtac
の許可回答に示されているように2回使用してください。tail -r
代わりに、次のようにMacOSで実装された答えは次のとおりです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/言語/operators#infix_??_!!
https://raku.org