Bash:echo 好还是 <<<?

-1 shell bash input shell-script base64

传递输入时,哪种方法更好?

 > echo 'test' | base64
dGVzdAo=

 > base64 <<< 'test'
dGVzdAo=
Run Code Online (Sandbox Code Playgroud)

对于变量,应该使用哪种方法?

 > t='test'

 > echo "$t" | base64
dGVzdAo=

 > base64 <<< "$t"
dGVzdAo=
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 5

<<<是here-string,here-document 的一种简短形式,由zsh(以及 的 Unix 端口rc)在 90 年代初引入,并从那时起复制(有变体)到许多其他 shell。

它的实现方式与 here-documents 相同。在包括zshand在内的大多数 shell 中bash,这是删除临时文件,因为 Bourne shell(在 70 年代后期引入 here-documents 的 shell)就是这样做的。

当你这样做时:

cmd <<< 'something'
Run Code Online (Sandbox Code Playgroud)

外壳执行以下操作:

file=$(mktemp)
printf 'something\n' > "$file"
{
  rm -f -- "$file" && cmd
} < "$file"
Run Code Online (Sandbox Code Playgroud)

(当然,所有mktemp, printf,rm都是在内部完成的,而不执行这些命令)。

一些 shell 使用管道和一个单独的进程(它可以是分叉命令或小的 here-docs/strings 的主要 shell 进程)来提供数据。某些 shell 可能会恢复使用/dev/nullfor empty here-docs(此处字符串不能为空,除非rc不添加换行符)。

在使用临时文件的实现中有几个优点。

  • 没有分叉的过程。
  • 输入是可搜索的(该命令可以在其输入中来回读取数据以在不同位置再次读取数据,而当其输入是管道时则无法这样做)。但是,您不能在可移植sh脚本中依赖它。

一些缺点:

  • 除了 in zsh,内容不能包含 NUL 字节
  • 除了 in rc,不可能提供不以换行符结尾的输入
  • 临时文件创建可能会失败(例如当没有剩余空间$TMPDIRumask某些实现过于严格时)。
  • 数据存储在永久存储器上。即使文件在它被删除之前被删除read,数据最终可能会被提交到磁盘,这意味着如果可以拿到磁盘,它可以被恢复。

在:

printf '%s\n' "$something" | cmd
Run Code Online (Sandbox Code Playgroud)

(这里 usingprintf而不是echoasecho不能用于任意数据)。

我们有两个同时运行的进程,一个通过管道将输出提供给另一个。当cmd是内置或复合命令或函数时,带有zsh或 AT&Tkshbash -o lastpipe,该命令在当前shell 中运行,否则在子进程中运行,因此诸如此类的事情echo x | read var不起作用。

这样做的一些优点:

  • 那是便携式的(与<<<,<<是便携式的相反)
  • 没有<<<上面提到的缺点
  • 要在 shell 中提供 NUL 字节,而不是zshzsh是唯一可以将 NUL 字节传递给内置命令的shell),您可以执行printf '\0' | cmd.

缺点:

  • 额外的进程以及cmd在某些 shell 的子进程中运行的事实,如上所述
  • 输入不可搜索。

请注意,如果您想要 的 base64 编码test,那就是:

printf test | base64
Run Code Online (Sandbox Code Playgroud)

或者

printf %s "$data" | base64
Run Code Online (Sandbox Code Playgroud)

对于任意数据。

您的为您提供了 .base64 编码test<newline>