Bash

接受來自參數或管道的輸入的 Bash 函式

  • September 3, 2020

我想以一種可以接受來自參數或管道的輸入的方式編寫以下 bash 函式:

b64decode() {
   echo "$1" | base64 --decode; echo
}

所需用途:

$ b64decode "QWxhZGRpbjpvcGVuIHNlc2FtZQo="
$ b64decode < file.txt
$ b64decode <<< "QWxhZGRpbjpvcGVuIHNlc2FtZQo="
$ echo "QWxhZGRpbjpvcGVuIHNlc2FtZQo=" | b64decode

請參閱Stéphane Chazelas 的答案以獲得更好的解決方案。


您可以使用/dev/stdin從標準輸入中讀取

b64decode()
{
   if (( $# == 0 )) ; then
       base64 --decode < /dev/stdin
       echo
   else
       base64 --decode <<< "$1"
       echo
   fi
}
  • $# == 0檢查命令行參數的數量是否為零
  • base64 --decode <<< "$1"也可以使用herestring而不是使用echo和管道到base64

這裡應該是:

b64decode() {
 if [ "$#" -gt 0 ]; then
   # concatenated arguments fed via a pipe.
   printf %s "$@" | base64 --decode
 else
   base64 --decode  # read from stdin
 fi
 ret=$?
 echo # add one newline character
 return "$ret" # return with base64's exit status to report decoding
               # errors if any.
}

在任何情況下,不要使用base64 --decode < /dev/stdin. 充其量(在大多數係統上)< /dev/stdin什麼都不做,它只是相當於dup2(0,0)(將 fd 0 複製到 fd 0,無操作)。

但是在 Linux 或 Cygwin 上,< /dev/stdin這裡不能正常工作。在這些系統上,打開/dev/stdin不像複製標準輸入,它會從頭開始重新打開,並且與目前在標準輸入上打開的文件相同。

因此,如果以前 stdin 指向某個正常文件的中間,那麼在 之後< /dev/stdin,您最終會看到 stdin 現在指向該文件的開頭。如果 stdin 是管道的寫入端(在正常情況下不應該這樣做),那麼您最終會成為讀取端。如果它是一個套接字,那麼它將失敗,因為套接字無法打開。如果您無權打開該文件進行讀取,則相同(例如,因為權限已更改或文件最初是使用不同的憑據在標準輸入上打開的)。

並且在base64 --decode < /dev/stdin返回之後,文件中的標準輸入的目前位置(用於可搜尋的文件輸入)將保持不變,不會留在最後(或base64停止讀取的地方),因為base64’s stdin 在不同的打開文件描述中。

引用自:https://unix.stackexchange.com/questions/301426