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.

다른 모든 레코드의 경우 원본 레코드를 출력하고 쉼표 뒤에 문자열을 추가합니다. 문자열은 두 개의 문자와 0으로 채워진 숫자로 평가됩니다. 두 문자가 범위에서 선택되고 [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 필드에 개행 문자가 포함되어 있지 않다고 가정합니다. 가능하다면 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

관련 정보