我想使用bash脚本将1个输入文件处理成2个输出文件,每个文件包含与输入文件相同数量的行,但输入行的不同部分。特别是其中一个输出文件必须包含输入行选择的md5hash(每行计算哈希值,而不是每个文件计算!):
所以
Input_file.txt:** 3个字段,以空格分隔
12347654 abcdfg 1verylongalpha1234numeric1
34543673 nvjfur 2verylongalpha1234numeric2
75868643 vbdhde 3verylongalpha1234numeric3
输出file_1.txt必须如下所示:(左侧字段为MD5sum,右侧字段为输入文件中的field3,也包含在MD5hash中):
12df5j754G75f738fjk3483df3fdf9 1verylongalpha1234numeric1
3jf75j47fh4G84ka9J884hs355jhd8 2verylongalpha1234numeric2
4hf7dn46chG4875ldgkk348fk345d9 3verylongalpha1234numeric3
输出file_2.txt必须如下所示:(输入文件中的field1和field2 + MD5HASH)
12347654 abcdfg 12df5j754G75f738fjk3483df3fdf9
34543673 nvjfur 3jf75j47fh4G84ka9J884hs355jhd8
75868643 vbdhde 4hf7dn46chG4875ldgkk348fk345d9
我已经有了一个可以完成工作的脚本,但它的表现非常糟糕:(下面的脚本可能无法正常工作,这是我的头脑,这里没有linux,我写这个,对不起)
#!/bin/bash
While read line
do MD5_HASH=${sed -nr 's/^[[:digit:]]*\s[[:alpha:]]*\s([[:alnum:]]*)/\1/p' <<<$line | md5sum}
read $line DATA_PART1 DATA_PART2 DATA_PART3
echo "$MD5_HASH $DATA_PART3" >> file_1.txt ##append file_2.txt in loop THIS IS WHERE IT GETS HORRIBLY SLOW!
echo "$DATA_PART1 $DATA_PART2 $MD5_HASH"
done < input_file.txt > file_2.txt
exit 0
我认为“将stdout重定向到带附加构造的文件”'&gt;&gt;'负责缓慢的表现,但我想不出另一种方式。它在循环中因为我必须计算每行的md5hash。
(哦,sed命令是必要的,因为实际上进入MD5SUM的部分只能用正则表达式和非常复杂的模式捕获)
所以任何人都有建议吗?
答案 0 :(得分:2)
您的bash脚本可以稍微整理一下。请注意,read
命令可以将3个字段读入单独的变量:
#!/bin/bash
rm -f file_1.txt file_2.txt
While read f1 f2 f3; do
hash=$(md5sum <<< $f3)
printf "%s %s\n" "$hash" "$f3" >> file_1.txt
printf "%s %s %s\n" "$f1" "$f2" "$hash" >> file_2.txt
done < input_file.txt
答案 1 :(得分:1)
这是我使用功能齐全的语言的一种情况,例如Python。
虽然您可以通过仅使用标准gnu工具找到一种方法来实现这一点,但您最终可能会得到一个解决方案:
from hashlib import md5
with open('input.txt', 'r') as infile:
for l in infile:
if not l.strip(): continue
parts = l.strip().split()
print md5(parts[2]).hexdigest(), parts[2]
from hashlib import md5
with open('input.txt', 'r') as infile:
for l in infile:
if not l.strip(): continue
parts = l.strip().split()
print parts[0], parts[1], md5(parts[2]).hexdigest()
我不确定你计算校验和的字段;但是,当然,你可以在你想要的任何一个领域进行计算;你还可以在线上执行更复杂的基于正则表达式的匹配;你可以通过一次输出两个文件来加快速度,从而避免两次计算md5。
from hashlib import md5
with open('infile.txt','r') as infile, open('out1.txt','w') as out1, open('out2.txt','w') as out2:
for l in infile:
if not l.strip(): continue
parts = l.strip().split()
_checksum = md5(parts[2]).hexdigest()
out1.write("%s\n" % " ".join([ _checksum, parts[2] ]))
out2.write("%s\n" % " ".join([ parts[0], parts[1], _checksum ]))
import sys
from hashlib import md5
for l in sys.stdin:
if not l.strip(): continue
parts = l.strip().split()
print md5(parts[2]).hexdigest(), parts[2]
答案 2 :(得分:1)
无法确定要计算md5的字符串,这个单行在整行上执行,并在'file1'和'file2'中输出处理后的'input_file':
awk '{ "md5 -q -s \""$0"\"" | getline md5;
print md5" "$3 > "file1";
print $1" "$2" "md5 > "file2" }' input_file
希望有所帮助......
答案 3 :(得分:0)
你可以从bash同时写两个文件,如下所示:
; function to remove extraneous filename output from md5sum. omit on
; OS X, which has 'md5' command that already works this way.
md5() { set -- $(md5sum "$@"); echo "$1"; }
exec 3>file_1.txt 4>file_2.txt
while read left middle right; do
md5="$(echo -n "$right" | md5)"
echo >&3 "$md5 $right"
echo >&4 "$left $middle $md5"
done <input_file.txt
exec 3>&- 4>&-
假设你的例子中有简单的空格分隔的字段;你当然还需要做任何sed
魔法来获得MD5总和的实际目标。
sed
的字段提取和MD5计算,所有这些都在循环过程中比shell快得多。输入线。 Perl例子:
perl -MDigest::MD5=md5_hex -lane '
BEGIN { open $f1, ">file_1.txt"; open $f2, ">file_2.txt" }
$md5 = md5_hex $F[2];
print $f1 "$md5 $F[2]";
print $f2 "$F[0] $F[1] $md5";
' input_file.txt
答案 4 :(得分:0)
您可以通过管道和并行来提高效率。
根据您的伪代码,您需要最后一个元素的md5总和:
paste -d ' ' \
input_file.txt \
<(cut -d' ' -f3 input_file.txt | parallel echo '{}' \| md5sum | cut -d' ' -f1) |
awk '{ print $4, $3 > "file_1.txt"; print $1, $2, $4 > "file_2.txt" }'
在进程替换中并行计算md5和,将此处的输出“粘贴”到原始文件上。最后,awk负责将输出放入正确的文件中。
我同意 redShadow ,这在shell中永远不会非常有效,因为你需要 子壳很多。这是perl中的另一种选择:
split.pl
use Digest::MD5 qw(md5_hex);
use v5.10;
open O1, ">file_1.txt" or die $!; open O2, ">file_2.txt" or die $!;
$, = " ";
while(<>) { chomp;
@F = split / +/;
$md5 = md5_hex $F[2];
say O1 $md5, $F[2];
say O2 @F[0,1], $md5;
}
close O1; close O2;
像这样跑:
<input_file.txt perl split.pl
两种情况下的输出:
file_1.txt
765ac5d0002aed1141a6a4e7b90e4ac9 1verylongalpha1234numeric1
b31901def07d436aed2c8028b2efa4ec 2verylongalpha1234numeric2
0722a6e50f6f8726f9754e7f71f9ad2c 3verylongalpha1234numeric3
file_2.txt
12347654 abcdfg 765ac5d0002aed1141a6a4e7b90e4ac9
34543673 nvjfur b31901def07d436aed2c8028b2efa4ec
75868643 vbdhde 0722a6e50f6f8726f9754e7f71f9ad2c