如何使用 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

这个 GNU Awk 命令拉入ord()函数ord.awk图书馆(与 GNU Awk 一起分发)能够在字符及其 ASCII 表示形式之间进行转换。然后,为了方便起见,它会初始化随机数生成器srand()并预先计算字母的 ASCII 值。AZ

如果当前记录是第一的记录(即,它是 CSV 标头),它会输出附加的字符串,CASENUMBER

对于所有其他记录,它输出原始记录并在逗号后附加字符串。该字符串被计算为两个字符和一个零填充的数字。这两个字符是从范围中选取的[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

我还将随机案例 ID 的创建移到了它自己的函数中,因为我们需要从代码的主要部分调用它两次。

答案2

perl

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

假设 CSV 字段不包含换行符。如果可以的话,您可以使用 perl 的Text::CSV模块像 miller 那样进行正确的 CSV 解析和格式化。

答案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 伦敦 UK4389223892 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

相关内容