Bash

子shell中的程序替換以設置變數

  • February 24, 2019

我正在嘗試遠端執行腳本並使用其標準輸出來填充變數。我這樣做是為了避免臨時文件。

這是我正在嘗試的模式:

var=$(bash <(curl -fsSkL http://remote/file.sh))
echo "var=${var}"

我正在測試這種模式而不curl使用cat

var=$(bash <(cat ./local/file.sh))
echo "var=${var}"

就語法而言,這應該是相同的。 ./local/file.shcontains echo hello,所以我希望var包含 value hello,但可惜的是,執行上述結果如下:

test.sh: command substitution: line 4: syntax error near unexpected token `('
test.sh: command substitution: line 4: `bash <(cat ./local/file.sh)'
var=

如何在不使用臨時文件的情況下實現我的目標?

bash這些是您在 shell 在 POSIX 模式下執行時嘗試執行程序替換時遇到的錯誤。bashshell 不支持 POSIX 模式下的程序替換。

bash將在 POSIX 模式下執行

  1. set -o posix已使用,或
  2. shell 被呼叫為sh.

我的預感是你有一個腳本,test.sh你正在執行sh test.sh或者有一個#!/bin/shhashbang 行,而你sh恰好是bash. 另一種可能性是腳本根本沒有*-line*#!,它是由bash-as-sh以其他方式呼叫的。

相反,請確保您的test.sh腳本被bash.

例子:

$ cat script.sh
echo hello
$ cat test.sh
var=$(bash <( cat script.sh ))
printf 'var="%s"\n' "$var"
$ bash -o posix test.sh
test.sh: command substitution: line 2: syntax error near unexpected token `('
test.sh: command substitution: line 2: `bash <( cat script.sh ))'
var=""
$ bash test.sh
var="hello"

如果您想test.sh使用 POSIX 在腳本中以可移植的方式執行此操作sh

var=$( cat script.sh | bash )
printf 'var="%s"\n' "$var"

這將產生程序在其標準輸入上bash讀取輸出的效果,這與您的程序替換變體(僅保留標準輸入)不太一樣。如果內部shell 執行的腳本從其標準輸入中讀取任何形式的數據,這很重要。cat``bash

如果您需要bash單獨保留 shell 的標準輸入(因為您需要從中讀取),您可能會假設它mktemp可用並使用

var=$( tmpfile=$(mktemp); cat script.sh >"$tmpfile" && bash "$tmpfile"; rm -f "$tmpfile" )
printf 'var="%s"\n' "$var"

Wherecat script.sh被理解為稍後被您的curl命令替換。

如果您對處理文件描述符感到滿意,您還可以在呼叫bashshell 之前使文件描述符 3 成為標準輸入描述符的副本,然後讓獲取的腳本從中讀取:

var=$( exec 3<&0; cat script.sh | bash )
printf 'var="%s"\n' "$var"

然後該script.sh腳本將用於read -u 3原始標準輸入流中讀取,或utility <&3將該輸入流重定向到另一個實用程序。

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