Bash

在沒有while循環的情況下使用bash的read builtin

  • February 12, 2015

我習慣了 while 循環中bash的內置函式,例如:read

echo "0 1
     1 1
     1 2
     2 3" |\
while read A B; do
   echo $A + $B | bc;
done

我一直在做一些make項目,拆分文件和儲存中間結果變得謹慎。因此,我經常最終將單行分解為變數。雖然以下範例執行良好,

head -n1 somefile | while read A B C D E FOO; do [... use vars here ...]; done

這有點愚蠢,因為 while 循環永遠不會執行超過一次。但沒有while,

head -n1 somefile | read A B C D E FOO; [... use vars here ...]

當我使用它們時,讀取的變數總是空的。我從未註意到 的這種行為read,因為通常我會使用 while 循環來處理許多類似的行。如何在沒有 while 循環的情況下使用bash‘s內置函式?read還是有另一種(甚至更好的)方法將單行讀入多個(!)變數?

結論

答案告訴我們,這是范圍界定的問題。該聲明

cmd0; cmd1; cmd2 | cmd3; cmd4

被解釋為命令cmd0,cmd1cmd4在相同的範圍內執行,而命令cmd2cmd3每個都有自己的子外殼,因此有不同的範圍。原始外殼是兩個子外殼的父外殼。

這是因為您使用 vars 的部分是一組新的命令。改用這個:

head somefile | { read A B C D E FOO; echo $A $B $C $D $E $FOO; }

請注意,在此語法中,在 之後必須有一個空格,在. 之前必須有{ 一個;(分號)}。也-n1沒有必要;read只讀取第一行。

為了更好地理解,這可能會對您有所幫助;它與上述相同:

read A B C D E FOO < <(head somefile); echo $A $B $C $D $E $FOO

編輯:

人們常說接下來的兩個語句做同樣的事情:

head somefile | read A B C D E FOO
read A B C D E FOO < <(head somefile)

嗯,不完全是。第一個是內置管道from to head。一個程序的標準輸出到另一個程序的標準輸入。bash``read

第二個語句是重定向和程序替換。它由bash自己處理。它創建一個 FIFO(命名管道,<(...)),它head的輸出連接到,並將其重定向(<)到read程序。

到目前為止,這些似乎是等價的。但是當使用變數時,它可能很重要。在第一個中,執行後未設置變數。在第二個中,它們在目前環境中可用。

在這種情況下,每個 shell 都有另一種行為。查看它們所在的連結bash您可以使用命令分組{}、程序替換 ( < <()) 或此處的字元串 ( ) 來解決該問題<<<

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