在沒有while循環的情況下使用bash的read builtin
我習慣了 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
,cmd1
和cmd4
在相同的範圍內執行,而命令cmd2
和cmd3
每個都有自己的子外殼,因此有不同的範圍。原始外殼是兩個子外殼的父外殼。
這是因為您使用 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
您可以使用命令分組{}
、程序替換 (< <()
) 或此處的字元串 ( ) 來解決該問題<<<
。