数値サフィックスを追加して重複を削除する

数値サフィックスを追加して重複を削除する

重複を排除するために行に数字のサフィックスを追加するには?

擬似コード:

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:カウンタを開始しますが、最初の一致のために1つを修正します。

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

カウントダウンにするにはtac2回使用してください。

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文を介した入力時に文を実行します%hashput行が/^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

関連情報