如何在bash中使用函数?

时间:2017-04-14 12:56:50

标签: linux bash unix awk openssl

我有一个文件,其中包含文件的哈希值。 例如,

fb7e0a4408e46fd5573ffb9e73aec021a9dcf426235c0ccfc37d2f5e09a68a23 /path/to/some/file
237e0a4408e46fe3573f239e73aec021a9dcf426235c023fc37d2f5e09a68a12 /path/to/another/file
... and so on...

我需要将哈希转换为base64编码格式。

所以我使用了bash函数和awk的组合。

这是我写的,

#!/bin/sh
base64Encode() {
     $1 | openssl base64 -A
}
awk ' { t = base64Encode $1; print t } ' file.txt

但它似乎不起作用。我正在使用hashdeep生成哈希列表文件,hashdeep不支持base64编码输出。这就是我使用openssl

的原因

任何关于此的帮助或提示都会很棒!

编辑:

给出的答案有效,但我似乎还有其他一些问题。

通常cat filename | openssl dgst -sha256 | openssl base64 -Abase64文件提供filename编码输出,这绝对是正确的, 来自hashdeep的{​​{1}}匹配输出的输出和输出。 所以,我想把上一步获得的输出汇总到cat filename | openssl dgst -sha256 openssl base64 -A输出。但是,我仍然从实际结果中得到不同的值。

虽然这可能适合单独的问题,但我仍然感谢对此的任何支持。

2 个答案:

答案 0 :(得分:1)

仅限Awk:

$ awk '{ c="echo " $1 "|openssl base64 -A"
         c | getline r
         print r }' file
ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo=
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

对于紧凑的单行版本,请参阅下面的@ 123的评论。

...和@ EdMorton的超紧(读:超级证明)版本。

答案 1 :(得分:1)

因为您特别要求如何使用函数,所以我将问题分成了几个小函数。这是所有(更大)的bash程序中的一个好习惯。

基本规则是:函数的行为与任何其他命令相同:

  • 您可以重定向他们的输入/输出
  • 你可以用参数调用它们
  • 等。

最好的功能就像普通的unix可执行文件,例如从stdin读取并打印到stdout。这允许您在管道中使用它们。

所以,现在重写:

# function for create base64 - reads from stdin, writes to stdout
base64Encode() {
        openssl base64 -A
}

# function for dealing with your file
# e.g. reads lines "hash path" and prints "base64 path"
convert_hashes() {
        while read -r hash path; do
                b64=$(base64Encode <<< "$hash")
                echo "$b64 $path"
        done
}

#the "main" program
convert_hashes < your_file.txt

输出

ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo= /path/to/some/file
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo= /path/to/another/file

是的,我知道,我只想要没有附加路径的base64。当然,您可以修改上面的convert_hashes并从输出中删除路径,例如而不是echo "$b64 $path"你可以使用echo "$b64"而输出只是b64字符串 - 但是你在函数中丢失信息 - 哪个字符串属于走哪条路 - 不是最好的做法。

因此,您可以按原样保留该功能,并使用其他工具获取第一列 - 并且仅在需要时 - 例如在“主要”计划中。通过这种方式,您可以设计一个函数,以便以后更通用。

convert_hashes < your_file.txt | cut -d ' ' -f1

输出

ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo=
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

现在想象一下,您扩展脚本,并且不想使用文件,但输入来自另一个程序:让我们使用以下get_data函数进行模拟(当然,在真正的应用程序中它会做其他的东西,不只是cat

get_data() {
cat <<EOF
fb7e0a4408e46fd5573ffb9e73aec021a9dcf426235c0ccfc37d2f5e09a68a23 /path/to/some/file
237e0a4408e46fe3573f239e73aec021a9dcf426235c023fc37d2f5e09a68a12 /path/to/another/file
EOF
}

现在您可以使用以上所有内容:

get_data | convert_hashes

输出与上面相同。

当然,你也可以对输出做些什么,比如说

get_data | convert_hashes | grep another/file | cut -d ' ' -f1
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

当然,如果你有这种“模块化”结构,你可以轻松更换任何部件,而无需触及其他部件,让我们说用openssl命令替换base64。 / p>

base64Encode() {
        base64
}

一切都会继续工作,没有任何其他变化。当然,在真正的应用程序中(可能)只有一个程序只能调用一个程序是没有意义的 - 但我特别这样做是因为你询问了这些函数。

否则,上述内容可以简单地完成:

while read -r hash path; do
    openssl base64 -A <<<"$hash"
    echo
    #or echo $(openssl base64 -A <<<"$hash")
    #or printf "%s\n" $(openssl base64 -A <<<"$hash")
done < your_file.txt

甚至

cut -d ' ' -f1 base  | xargs -I% -n1 bash -c 'echo $(openssl base64 -A <<<"%")'

您需要echoprint,因为openssl默认情况下不会打印换行符。输出:

ZmI3ZTBhNDQwOGU0NmZkNTU3M2ZmYjllNzNhZWMwMjFhOWRjZjQyNjIzNWMwY2NmYzM3ZDJmNWUwOWE2OGEyMwo=
MjM3ZTBhNDQwOGU0NmZlMzU3M2YyMzllNzNhZWMwMjFhOWRjZjQyNjIzNWMwMjNmYzM3ZDJmNWUwOWE2OGExMgo=

Ps:老实说,我不明白为什么你需要base64编码一些已编码的哈希 - 但是YMMV。 :)