複数行の照会、ハッシュ、および置換の並行性

複数行の照会、ハッシュ、および置換の並行性

複数のファイルがあり、各行にはハッシュを使用してマスクしたい固有の値があります。

ところがファイルに300万行があるが、その過程を完了するのにかかる時間をおおよそ計算すれば32日という非常に長い時間だ。

for y in files*; do 
  cat $y | while read z; do
    KEY=$(echo $z | awk '{ print $1 }' | tr -d '"')
    HASH=$(echo $KEY | sha1sum | awk '{ print $1 }')
    sed -i -e "s/$KEY/$HASH/g" $y
  done
done

このプロセスをスピードアップするには、並行性を導入する必要があると思います。

急な試みに基づいてhttps://unix.stackexchange.com/a/216475私を連れて行く

N=4
(
for y in gta*; do 
  cat $y | while read z; do
    (i=i%N)); ((i++==0)); wait
    ((GTA=$(echo $z | awk '{ print $1 }' | tr -d '"')
    HASH=$(echo $GTA | sha1sum | awk '{ print $1 }')
    sed -i -e "s/$KEY/$HASH/g) & 
  done
done
)

そのパフォーマンスは良くありません。

入力例

"2000000000" : ["200000", "2000000000"]
"2000000001" : ["200000", "2000000001"]

出力例

"e8bb6adbb44a2f4c795da6986c8f008d05938fac" : ["200000", "e8bb6adbb44a2f4c795da6986c8f008d05938fac"]
"aaac41fe0491d5855591b849453a58c206d424df" : ["200000", "aaac41fe0491d5855591b849453a58c206d424df"]

たぶん同時に行を読み、次に各行でハッシュ置換を実行する必要がありますか?

答え1

FWIW私はこれがシェルスクリプトでこれを行う最速の方法だと思います。

$ cat tst.sh
#!/usr/bin/env bash

for file in "$@"; do
    while IFS='"' read -ra a; do
        sha=$(printf '%s' "${a[1]}" | sha1sum)
        sha="${sha% *}"
        printf '%s"%s"%s"%s"%s"%s"%s"\n' "${a[0]}" "$sha" "${a[2]}" "${a[3]}" "${a[4]}" "$sha" "${a[6]}"
    done < "$file"
done

$ ./tst.sh file

$ cat file
"e8bb6adbb44a2f4c795da6986c8f008d05938fac" : ["200000", "e8bb6adbb44a2f4c795da6986c8f008d05938fac"]"
"aaac41fe0491d5855591b849453a58c206d424df" : ["200000", "aaac41fe0491d5855591b849453a58c206d424df"]"

しかし、私がコメントで述べたように実行速度を向上させるには、sha1sum機能を備えたツール(Pythonなど)を使用することをお勧めします。

答え2

Pythonの助けを借りて、Ed Mortonの提案に従います。

Pythonスクリプト/tmp/sha1.pyを作成して実行可能にします。

#! /usr/local/bin/python -u

import hashlib
import sys

for line in sys.stdin:
  words = line.split()
  str_hash=hashlib.sha1(words[0].encode())
  words[0] = str_hash.hexdigest()
  print(" ".join(words))

最初の行にはPythonの正しい場所を含める必要がありますが、「-u」は削除しないでください。

その後、実行可能にする必要があるkshスクリプトがあります。

#! /usr/bin/ksh

/tmp/sha1.py |&

for y in files*
do
  while read A B
  do
    eval "echo $A" >&p
    read A <&p
    echo \"$A\" $B
  done < $y > TMP.$y
  mv TMP.$y $y
done

# terminate sha1.py
exec 3>&p
exec 3>&-

パフォーマンスが必要な場合は、Pythonに一度に1つの完全なファイルを処理させる必要があります。次のスクリプトは、各入力行をファイル名として処理し、汚れた操作を実行します。

#! /usr/local/bin/python

import hashlib
import os
import sys

for IFileNmX in sys.stdin:
  IFileNm = IFileNmX.strip()
  IFile = open(IFileNm,'r')
  OFileNm = ".".join(["TMP",IFileNm])
  OFile = open(OFileNm,'w')
  for line in IFile.readlines():
    words = line.split()
    word1 = words[0].strip('"')
    str_hash=hashlib.sha1(word1.encode())
    words[0] = "".join(['"',str_hash.hexdigest(),'"'])
    OFile.write("".join([" ".join(words),'\n']))
  OFile.close()
  IFile.close()
  os.rename(OFileNm,IFileNm)

このスクリプト/tmp/sha1f.pyを呼び出して実行可能にするのに何分かかるのか知りたいです。

ls files* | /tmp/sha1f.py

奪われるだろう。私のシステムは、400Mb、100万行のファイルを処理するのに12秒かかりました。しかし、これはもちろん誇りです。

関連情報