Millerを使用して新しい列を作成し、任意の識別子を追加する方法

Millerを使用して新しい列を作成し、任意の識別子を追加する方法

csvランダムに生成された「イベント番号」を含む列を私のファイルに追加したいと思います。事件番号の最初の2文字はAZの大文字でなければなりません。以下は5つの乱数です。

入力する:

COMPANY,NAME,STREET,ZIP,CITY,IBAN
Test Ltd,John,Big Ben 343,4343,London,UK2348020384
Test Ltd,Kate,Big Ben 343,4343,London,UK4389223892
Test Ltd,Jake,Big Ben 343,4343,London,UK3892898999

出力

COMPANY,NAME,STREET,ZIP,CITY,IBAN,CASENUMBER
Test Ltd,John,Big Ben 343,4343,London,UK2348020384,IN84903
Test Ltd,Kate,Big Ben 343,4343,London,UK4389223892,TY93842
Test Ltd,Jake,Big Ben 343,4343,London,UK3892898999,OL34307

ミラーでこれを行うにはどうすればよいですか?次のコマンドを準備しました

mlr -I --csv put '${CASENUMBER}=xxx' then \
    reorder -f COMPANY,NAME,STREET,ZIP,CITY,IBAN,CASENUMBER input/input.csv

上記のコマンドに正確に何を追加する必要がありますか?

答え1

これはMillerを使用しませんが(主にランダムな文字を処理する便利な方法が見つからないため)、GNU Awkは次のようになります。

awk -i ord -v OFS=, '
    function randint(n) { return int(n*rand()) }
    BEGIN { srand(); A = ord("A"); Z = ord("Z") }
    NR == 1 { printf("%s,CASENUMBER\n", $0); next }
    { printf "%s,%c%c%.5d\n", $0, A + randint(Z-A+1), A + randint(Z-A+1), randint(100000) }' file.csv

ord()このGNU Awkコマンドは機能を取得します。ord.awk図書館から(GNU Awkと共に配布されています)文字と対応するASCII表現の間の変換機能。次に、便宜上、乱数ジェネレータを初期化し、srand()文字のASCII値を事前に計算します。AZ

現在の記録が以下の場合最初レコード(つまり、CSVヘッダー)の場合は、追加された文字列を出力します,CASENUMBER

他のすべてのレコードの場合は、元のレコードを出力し、カンマの後に文字列を追加します。文字列は、2 つの文字とゼロで埋められた数字で評価されます。 2文字が範囲で選択され[A,Z]、数字も範囲で選択されます[0,100000)。この関数を使用して、範囲内の任意の整数を選択しますrandint()。変更されていない関数を使用しています。GNU Awkマニュアルから

指定されたデータに対してこのコマンドを実行する出力の例:

COMPANY,NAME,STREET,ZIP,CITY,IBAN,CASENUMBER
Test Ltd,John,Big Ben 343,4343,London,UK2348020384,HP88271
Test Ltd,Kate,Big Ben 343,4343,London,UK4389223892,XS17910
Test Ltd,Jake,Big Ben 343,4343,London,UK3892898999,UX00409

フィールドに改行文字が含まれていないと仮定する限り、実際には必要ありません。分析する入力データ。この仮定では、各行の最後に新しいデータを追加するだけで十分です。


Terdonがコメントで指摘しました。計算されたケースIDが一意であることを確認することをお勧めします。これは、次の連想配列で生成されたIDを追跡することによって行われますseen

awk -i ord -v OFS=, '
    function randint(n) { return int(n*rand()) }
    function randid() { return sprintf("%c%c%.5d", A + randint(Z-A+1), A + randint(Z-A+1), randint(100000)) }

    BEGIN { srand(); A = ord("A"); Z = ord("Z") }
    NR == 1 { printf("%s,CASENUMBER\n", $0); next }
    {
        id = randid()
        while (seen[id]++ > 0) id = randid()
        printf "%s,%s\n", $0, id
    }' file.csv

また、コードの主要部分でこれを2回呼び出す必要があるため、ランダムなケースIDの生成を独自の関数に移動しました。

答え2

そしてperl

perl -lpe '$_ .= $. == 1 ? ",CASENUMBER" : sprintf ",%s%s%05d", ("A".."Z")[rand 26,rand 26], rand 1e5'

CSVフィールドに改行文字が含まれていないとします。可能であれば、Text::CSV適切なCSV解析とフォーマットのために、millerなどのPerlモジュールを使用できます。

答え3

ミラーの方法。

alphabet="[\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\"]"

mlr --csv put '$CASENUMBER=urandelement('"$alphabet"').urandelement('"$alphabet"').substr0(urand32(),0,5)' input.csv

あなたはやる

会社 名前 ストリート 圧縮 都市 国際銀行口座番号 イベント番号
テスト会社 ビッグベン343 4343 ロンドン UK2348020384 BV134526
テスト会社 ケイト ビッグベン343 4343 ロンドン イギリス4389223892 ZF321045
テスト会社 ジャック ビッグベン343 4343 ロンドン イギリス 3892898999 VQ302039

答え4

awkを使用してください。

$ cat tst.sh
#!/usr/bin/env bash

[[ -s /dev/urandom ]] && seed="$(od -An -N4 -tu4 /dev/urandom)"

awk -v seed="$seed" '
    BEGIN {
        if (seed) srand(seed); else srand()
        FS = OFS = ","

        chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        numChars = length(chars)
        for ( i=1; i<=numChars; i++ ) {
            for ( j=1; j<=numChars; j++ ) {
                strs[++numStrs] = substr(chars,i,1) substr(chars,j,1)
            }
        }

        numDigitCols = 5
        numNumbers = length("0123456789") ^ numDigitCols
        maxUnqAttempts = 100
    }

    {
        for ( attempts=1; attempts<=maxUnqAttempts; attempts++ ) {
            id = sprintf( "%s%05g", strs[int(1+rand()*numStrs)], int(rand()*numNumbers) )
            if ( !seen[id]++ ) {
                break
            }
        }

        if ( attempts > maxUnqAttempts ) {
            printf "%s[%d]: Failed to generate a unique ID after %d attempts, reusing %s\n", FILENAME, NR, maxUnqAttempts, id | "cat>&2"
        }

        print $0, (NR>1 ? id : "CASENUMBER")
    }

' "${@:--}"

$ ./tst.sh input.csv
COMPANY,NAME,STREET,ZIP,CITY,IBAN,CASENUMBER
Test Ltd,John,Big Ben 343,4343,London,UK2348020384,TT93580
Test Ltd,Kate,Big Ben 343,4343,London,UK4389223892,MP70836
Test Ltd,Jake,Big Ben 343,4343,London,UK3892898999,TM77788

関連情報