如何使用 miller 创建新列并向其添加随机标识符

pwr*_*ler 3 linux shell text-processing csv 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
Run Code Online (Sandbox Code Playgroud)

输出

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
Run Code Online (Sandbox Code Playgroud)

如何与米勒一起做到这一点?我准备好了以下命令

mlr -I --csv put '${CASENUMBER}=xxx' then \
    reorder -f COMPANY,NAME,STREET,ZIP,CITY,IBAN,CASENUMBER input/input.csv
Run Code Online (Sandbox Code Playgroud)

到底要在上面的命令中添加什么?

Kus*_*nda 5

这不使用 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
Run Code Online (Sandbox Code Playgroud)

此 GNU Awk 命令ord()(与 GNU Awk 一起分发)中提取函数,以便能够在字符及其 ASCII 表示形式之间进行转换。然后,为了方便起见,它会初始化随机数生成器并预先计算字母的 ASCII 值。ord.awksrand()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
Run Code Online (Sandbox Code Playgroud)

请注意,只要我们假设没有字段包含嵌入的换行符,我们就不需要实际解析输入数据。有了这个假设,只需将新数据附加到每行的末尾就足够了。


terdon 在评论中指出,确保计算出的案例 ID 是唯一的可能是一个好主意。这是通过在名为 的关联数组中跟踪已生成的 ID 来实现的seen

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
Run Code Online (Sandbox Code Playgroud)

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