ファイル内の各行の列値をコマンドの出力にすばやく効率的に置き換える方法を見つけようとしています。 1日に50万行程度の複数のファイルを処理する必要がありますが、できるだけ早く作業を終了できることを探しています。
コンマで区切られた行の8番目の列を入力に取り、コマンドを実行し、その列をコマンドの出力に置き換える必要があります。
私が試した方法は次のとおりです。動作しますが、非常に遅いです。
awk -F "," 'NR > 1 {
cmd = "cdrtoip " $8
cmd | getline ip
close(cmd)
$8=ip
print
}' $1.csv >> $1.csv.tmp
私はBashやLinuxサーバーにプリインストールできる他のLinuxプログラムを使用することを好みます。
編集:申し訳ありません。 cdrtoipが何であるかを含める必要がありました。
# Convert CISCO format (signed integer) to Hex
# Capitalize or else conversion from hex to decimal doesn't work later
HEXIP=$(printf '%x\n' $1 | tr '[:lower:]' '[:upper:]')
# Negative numbers will get 8 'f' in front of them
# Trim that part off
if [[ ${#HEXIP} -eq 16 ]]; then
HEXIP=${HEXIP:8:8}
fi
# Convert hex to decimal, separate into octets, put in order
OCTETS[0]=$(echo "ibase=16; ${HEXIP:6:2}" | bc)
OCTETS[1]=$(echo "ibase=16; ${HEXIP:4:2}" | bc)
OCTETS[2]=$(echo "ibase=16; ${HEXIP:2:2}" | bc)
OCTETS[3]=$(echo "ibase=16; ${HEXIP:0:2}" | bc)
# Print the IP
echo ${OCTETS[0]}.${OCTETS[1]}.${OCTETS[2]}.${OCTETS[3]}
cdripの実行時間は次のとおりです。
0.23s real 0.00s user 0.02s system
ベストアンサー1
ネイティブアプリを使い続けたいと言っているのはわかりますが、GNUパラレル別々のプロセスを並列に実行できるため、より高速に実行できます。
sudo apt-get update
sudo apt-get install parallel
awk -F',' '{print $8}' file.csv | parallel -j+0 cdrtoip {}
これを呼び出す方法はいくつかありますが、parallel
上記の方法は.csvファイルの列8から出力を取得し、cdrtoip
システムの各行でコアごとに1つのプロセスを同時に実行します。したがって、デフォルトで4つのコアを実行すると、通常の実行時間の25%以内にタスクを実行できます。
利点parallel
は、出力を追跡し、実行中のタスクであるかのように順番に生成することです。
インストールしたら、man parallel
実行方法の詳細を確認してください(またはリンクのマニュアルを確認してください)。これがあなたが探しているものではない場合は申し訳ありません。しかし、過去には何度も役に立ちました。
編集する:出力を.csvに追加して列8を置き換えるには、次の例を使用します。〜する働いて、持つテスト済みです。デュアルコアMacbook Proで5,000行の.csvファイルを実行するのに約3.25分かかります。
設定:
$ cat file.tmp
blah1,blah2,blah3,blah4,blah5,blah6,blah7,1175063050,blah9,blah10,blah11
$ for i in {1..5000}; do cat file.tmp; done > file.csv
$ wc -l < file.csv
5000
スクリプト(cdrtoip
提供されたスクリプトを使用):
$ cat csvjob.sh
#!/bin/bash
fragment1="$(cut -d, -f1-7 file.csv | tr ',' "\t")"
fragment2="$(cut -d, -f8 file.csv | parallel -j+0 cdrtoip {})"
fragment3="$(cut -d',' -f9- file.csv | tr ',' "\t")"
paste <(echo "$fragment1") <(echo "$fragment2") <(echo "$fragment3") | sed "s/\t/,/g" > newfile.csv
結果:
$ time ./csvjob.sh
real 3m23.092s
user 1m22.245s
sys 2m57.794s
$ head -3 newfile.csv
blah1,blah2,blah3,blah4,blah5,blah6,blah7,10.10.10.70,blah9,blah10,blah11
blah1,blah2,blah3,blah4,blah5,blah6,blah7,10.10.10.70,blah9,blah10,blah11
blah1,blah2,blah3,blah4,blah5,blah6,blah7,10.10.10.70,blah9,blah10,blah11
別の編集: 以下はクアッドコアのMac Miniで実行されました(他のものも実行)。
$ time ./csvjob.sh
real 2m12.171s
user 2m59.816s
sys 2m15.787s
また、5,000行ではなく500,000行と言われたことに気づきました。その価値が何であるかについては、cdrtoip
5,000回の連続実行に関する以下の統計を参照してください。
$ time for i in {1..5000}; do cdrtoip 1175063050; done > /dev/null
real 2m32.487s
user 1m26.537s
sys 1m8.270s
最終編集: 以下は、前述のように、すでに複数のアプリケーションを実行しているクアッドコアMac Miniで実行されている500,000行のファイルです。
$ time ./csvjob.sh
real 216m22.780s
user 301m40.694s
sys 239m44.404s
何を言うのか正確に知っている、OP。
並行して実行しても実行にはかなり長い時間がかかります。
OPはより良い解決策を見つけました。ファイルあたり126秒は他の追随を許しません。繰り返しますが、cdrtoip
元々提供された500,000行の.csvを8コアDebian VM(OPがインストールできないことを知っています)で実行した統計は次のとおりです。parallel
$ time ./csvjob.sh
real 14m7.467s
user 6m3.883s
sys 4m18.556s