1

我想使用 bash 脚本将 1 个输入文件处理为 2 个输出文件,每个文件包含与输入文件相同的行数,但输入行的不同部分。特别是其中一个输出文件必须包含输入行选择的 md5hash,(每行计算的哈希,而不是每个文件!):

所以

Input_file.txt: ** 3 个字段,以空格分隔

12347654 abcdfg 1verylongalpha1234numeric1

34543673 nvjfur 2verylongalpha1234numeric2

75868643 vbdhde 3verylongalpha1234numeric3

输出文件_1.txt 必须如下所示:(左字段是 MD5sum,右字段是来自输入文件的字段 3,它也包含在 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

我认为“使用附加结构将标准输出重定向到文件”'>>' 是造成性能缓慢的原因,但我想不出另一种方法。它在循环中,因为我必须计算每行的 md5hash。

(哦,sed 命令是必要的,因为实际上进入 MD5SUM 的部分只能用正则表达式和相当复杂的模式捕获)

所以有人有建议吗?

4

5 回答 5

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
于 2012-11-08T21:46:47.613 回答
1

这是我将使用功能齐全的语言(例如 Python)的一种情况。

尽管您可能会找到一种仅使用标准 gnu 工具来完成此操作的方法,但您很可能最终会得到一个解决方案:

  • 非常复杂,难以阅读和维护
  • 效率低下,因为这些工具没有提供直接的方法来做到这一点。

1.在Python中创建第一个文件

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]

2.在Python中创建第二个文件

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 两次。

3.一次创建两个文件

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 ]))

4. 与 #1 相同,但从标准输入读取

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]
于 2012-11-08T12:37:23.253 回答
1

无法确定您要为哪个字符串计算 md5,这个单行程序在整行上执行,并在“file1”和“file2”中输出处理后的“input_file”:

awk '{ "md5 -q -s \""$0"\"" | getline md5; 
     print md5" "$3 > "file1"; 
     print $1" "$2" "md5 > "file2" }' input_file

希望能帮助到你..

于 2012-11-08T12:51:15.967 回答
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为了获得更好的性能,您应该使用 Perl 或 Python 之类的东西,它们可以在一个进程中完成您正在使用的字段提取和 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
于 2012-11-08T12:45:37.113 回答
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 中永远不会非常有效,因为您需要进行很多子 shell。这是 perl 中的一个替代方案:

分裂.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

两种情况下的输出:

文件_1.txt

765ac5d0002aed1141a6a4e7b90e4ac9 1verylongalpha1234numeric1
b31901def07d436aed2c8028b2efa4ec 2verylongalpha1234numeric2
0722a6e50f6f8726f9754e7f71f9ad2c 3verylongalpha1234numeric3

文件_2.txt

12347654 abcdfg 765ac5d0002aed1141a6a4e7b90e4ac9
34543673 nvjfur b31901def07d436aed2c8028b2efa4ec
75868643 vbdhde 0722a6e50f6f8726f9754e7f71f9ad2c
于 2012-11-08T13:44:35.247 回答