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値を事前に計算します。A
Z
現在の記録が以下の場合最初レコード(つまり、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