1

bash スクリプトを使用して、1 つの入力ファイルを 2 つの出力ファイルに処理したいと考えています。それぞれのファイルには、入力ファイルと同じ行数が含まれていますが、入力行の異なる部分が含まれています。特に、出力ファイルの 1 つには、選択した入力行の md5hash が含まれている必要があります (ファイルごとではなく、行ごとに計算されたハッシュ!):

そう

Input_file.txt: ** スペースで区切られた 3 つのフィールド

12347654 abcdfg 1verylongalpha1234numeric1

34543673 nvjfur 2verylongalpha1234numeric2

75868643 vbdhde 3verylongalpha1234numeric3

出力 file_1.txt は次のようになります: (左のフィールドは MD5sum で、右のフィールドは MD5hash にも含まれる入力ファイルの field3 です):

12df5j754G75f738fjk3483df3fdf9 1verylongalpha1234numeric1

3jf75j47fh4G84ka9J884hs355jhd8 2verylongalpha1234numeric2

4hf7dn46chG4875ldgkk348fk345d9 3verylongalpha1234numeric3

出力 file_2.txt は次のようになります: (入力ファイルの field1 と field2 + MD5HASH)

12347654 abcdfg 12df5j754G75f738fjk3483df3fdf9

34543673 nvjfur 3jf75j47fh4G84ka9J884hs355jhd8

75868643 vbdhde 4hf7dn46chG4875ldgkk348fk345d9

私はすでにその仕事をするスクリプトを持っていますが、それは非常にうまく機能しません: (以下のスクリプトはうまくいかないかもしれません.

#!/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 を計算する必要があるため、ループ内にあります。

(そして、実際にはMD5SUMに入る部分は正規表現と非常に複雑なパターンでしかキャプチャできないため、sedコマンドが必要です)

それで、誰か提案がありますか?

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 などの完全な機能を備えた言語を使用する 1 つのケースです。

標準の 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 で 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()

どのフィールドでチェックサムを計算したかわかりません。ただし、もちろん、必要なフィールドで計算できます。行に対してより複雑な正規表現ベースのマッチングを実行することもできます。2 つのファイルを一度に出力することで処理を高速化できるため、md5 を 2 回計算する必要がなくなります。

3. 2 つのファイルを一度に作成する

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 を計算する文字列を特定できませんでした。このワンライナーは行全体で実行し、処理された「input_file」を「file1」と「file2」に出力します。

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

パイプやパラレルで効率を上げられるかもしれません。

疑似コードによると、最後の要素の 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に同意します。これが 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

どちらの場合も出力:

file_1.txt

765ac5d0002aed1141a6a4e7b90e4ac9 1verylongalpha1234numeric1
b31901def07d436aed2c8028b2efa4ec 2verylongalpha1234numeric2
0722a6e50f6f8726f9754e7f71f9ad2c 3verylongalpha1234numeric3

file_2.txt

12347654 abcdfg 765ac5d0002aed1141a6a4e7b90e4ac9
34543673 nvjfur b31901def07d436aed2c8028b2efa4ec
75868643 vbdhde 0722a6e50f6f8726f9754e7f71f9ad2c
于 2012-11-08T13:44:35.247 に答える
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 合計の実際のターゲットを取得するために必要な あらゆる魔法を実行する必要があります。

ただし、あまり効率的ではありません。パフォーマンスを向上させるには、Perl や Python のようなものを使用する必要があります。これは、使用しているフィールド抽出sedと MD5 計算の両方をすべて単一のプロセス内で実行でき、入力行のループでシェルよりもはるかに高速です。パールの例:

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 に答える