ken*_*orb 3 bash io-redirection shell-script paste
我有以下脚本:
#!/usr/bin/env bash
# Script to generate MD5 hash for each line.
[ $# -eq 0 ] && { echo "Usage: $0 file"; exit 1; }
file=$1
shopt -s expand_aliases
alias calc_md5='while read -r line; do md5sum <<<$line; done'
paste <(sort "$file" | uniq | calc_md5) <(sort "$file" | uniq)
times
Run Code Online (Sandbox Code Playgroud)
它并排打印每行的 MD5 校验和,这正是我需要的。例如:
$ ./md5_lines.sh file.dat
5c2ce561e1e263695dbd267271b86fb8 - line 1
83e7cfc83e3d1f45a48d6a2d32b84d69 - line 2
0f2d633163ca585e5fc47a510e60f1ff - line 3
73bb3632fc91e9d1e1f7f0659da7ec5c - line 4
Run Code Online (Sandbox Code Playgroud)
上述脚本的问题在于它需要为每个列/流读取和解析文件两次。理想情况下,我想对所有行进行排序并使所有行都是唯一的,并且仅将其用作输入一次。
如何将上述脚本转换为仅解析一次文件 ( sort
& uniq
),然后将输出重定向到两个不同的流并并排显示行,以便它可以更快地处理较大的文件?
这是我的另一个尝试:
tee >(calc_md5) >(cat -) \
< <(sort "$file" | uniq) \
>/dev/null
times
Run Code Online (Sandbox Code Playgroud)
但它单独打印流(不是并排)。
理想情况下,我想以paste
与 相同的方式使用tee
,但是它给了我错误:
$ paste >(cat -) >(cat -) </etc/hosts
paste: /dev/fd/63: Permission denied
Run Code Online (Sandbox Code Playgroud)
如果你想并排显示两个东西,你可以使用 printf 进行格式化打印。
#!/bin/bash
sort "$1" | uniq | while read line; do
md5=$(md5sum <<< "$line")
printf "%s %s\n" "$md5" "$line"
done
times
Run Code Online (Sandbox Code Playgroud)
一些 Perl 方法:
使用 Perl 获取 md5sum
$ perl -ne 'BEGIN{
use Digest::MD5 qw(md5_hex)
}
$k{$_}=md5_hex("$_");
END{
print "$k{$_} - $_" for sort keys(%k)
}' file
5c2ce561e1e263695dbd267271b86fb8 - line 1
83e7cfc83e3d1f45a48d6a2d32b84d69 - line 2
0f2d633163ca585e5fc47a510e60f1ff - line 3
73bb3632fc91e9d1e1f7f0659da7ec5c - line 4
d82912361d84a675530f5e32aa6eeda1 - line 5
Run Code Online (Sandbox Code Playgroud)
是的,这是一个单班轮:
perl -ne 'BEGIN{use Digest::MD5 qw(md5_hex)} $k{$_}=md5_hex("$_"); END{print "$k{$_} - $_" for sort keys(%k)}' file
Run Code Online (Sandbox Code Playgroud)
这应该比在 shell 中进行这种处理要快得多。
使用系统调用
perl -ne 'BEGIN{use Digest::MD5 qw(md5_hex)} $k{$_}=md5_hex("$_"); END{print "$k{$_} - $_" for sort keys(%k)}' file
Run Code Online (Sandbox Code Playgroud)