Shell-Script

在 Bourne Shell 中讀取多行

  • May 11, 2020

我正在嘗試將兩行讀入兩個變數。在 Bash 我會使用這樣的東西:

cat << EOF > myfile
line1
line2
EOF

cat myfile |  {
read firstline
echo $firstline # "line1" in bash and sh
read secondline
}

echo $firstline # "line1" in bash, empty in sh
echo $secondline

然而,在 Bourne Shell 中$firstline並且$secondline在命令組之外是空的。我怎樣才能在sh中做到這一點?

(您很可能firstline在 中測試該程式碼時已經設置bash,它的值最後應該為空)。

執行管道時

cat myfile | { read firstline; read secondline; }

右側在子外殼中執行。不是因為,{ ...; }而是因為它是管道的一部分。subshel​​l 環境將包含兩個變數firstlineand secondline(在兩個變數都被讀取之後),但是當 subshel​​l 終止時將被銷毀,丟棄這兩個變數。

這適用於 POSIXshbash.

在(4.2+) 中,您可以通過設置shell 選項bash來解決此問題。lastpipebash手冊:

管道中的每個命令都作為單獨的程序執行(即,在子shell 中)。有關子 shell 環境的描述,請參閱命令執行環境。如果使用內置lastpipe啟用該選項 (請參見下面的描述),則管道的最後一個元素可能由 shell 程序執行。shopt``shopt

這將在腳本中起作用,但在啟用了作業控制的互動式 shell 中不起作用(是作業控制使它不起作用,而不是互動性)。

例子:

$ cat script.sh
cat << EOF > myfile
line1
line2
EOF

cat myfile | { read firstline; read secondline; }
printf 'first=%s\n' "$firstline"
printf 'second=%s\n' "$secondline"

shopt -s lastpipe
cat myfile | { read firstline; read secondline; }
printf 'first=%s\n' "$firstline"
printf 'second=%s\n' "$secondline"
$ bash script.sh
first=
second=
first=line1
second=line2

在您的特定情況下,您還可以在 POSIXshbash中完全取消和管道,而是直接使用兩個呼叫cat重定向到復合命令:read

{ read firstline; read secondline; } <myfile

順便說一句,您的機器上很可能沒有真正的歷史 Bourne shell(除非它是 Solaris 11 之前的 Solaris 系統)。我假設您的意思是現代 POSIX shshell。

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