![跨大量行的查找、哈希值和替换的并发性](https://linux22.com/image/184775/%E8%B7%A8%E5%A4%A7%E9%87%8F%E8%A1%8C%E7%9A%84%E6%9F%A5%E6%89%BE%E3%80%81%E5%93%88%E5%B8%8C%E5%80%BC%E5%92%8C%E6%9B%BF%E6%8D%A2%E7%9A%84%E5%B9%B6%E5%8F%91%E6%80%A7.png)
我有一堆文件,每一行都有一个唯一的值,我试图用哈希来掩盖。
然而,文件中有 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 我认为这是在 shell 脚本中执行此操作的最快方法:
$ 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
按照 Ed Morton 的建议,在 python 的帮助下。
创建一个 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 一次处理一个完整的文件。以下脚本将每个输入行视为一个文件名,并完成您的肮脏工作:
#! /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
将采取。我的系统花了 12 秒来处理一个 400Mb、一百万行的文件。但这当然是自夸。