如何解析输入文件一次并发送到两个单独的流并并排显示?

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)

Cap*_*les 8

如果你想并排显示两个东西,你可以使用 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)


ter*_*don 5

一些 Perl 方法:

  1. 使用 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 中进行这种处理快得多。

  2. 使用系统调用

    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)

  • 你的 _2,_ 部分有几个问题,比如需要一个 zsh 兼容的 sh 来实现 `&lt;&lt;&lt;`,这是一个 ACE 漏洞(`$_` 被解释为 shell 代码!),当然效率会比一个“while read”循环,因为除了一个 md5sum 之外,您还每行运行一个 shell(甚至不是一个唯一的行)。 (2认同)