![](/img/trans.png)
[英]How to pipe input to a Bash while loop and preserve variables after loop ends
[英]How to pipe while loop input to the encapsulated commands after the “do”
我的目的是在下載文件時抓取(然后修改)cURL輸出。
curl -# -L --user-agent 'Mozilla/5.0' -o "`echo -e "$filename"`" "$url" 2>&1 |
while true
do
read <&1 line1 line2
echo $line2
if [ "`echo $line2 | grep -o "#"`" = "#" ] ; then
echo "downloading..."
break
elif [ "`echo $line2 | grep -o "curl"`" = "curl" ] ; then
echo $line2
break
else
echo "stderr still empty"
fi
done
問題是,卷曲輸出(被發送到stderr)是動態的,所以我覺得我必須使用while true
到東西可以讀,因為如果我立即通過管道while read
后curl
,管道是空的。
知道我想直接將curl輸出發送到上面構造中的讀取輸入。
我真的不想使用任何臨時文件(這很容易解決這個問題我同意:))
編輯:這是存儲在日志中的stderr上的curl動態curl輸出:
######################################################################## 100.0%
0.2%
0.5%
1.1%
# 1.6%
# 2.6%
## 3.3%
### 4.6%
#### 6.1%
#### 6.5%
#### 6.8%
##### 7.3%
##### 7.7%
##### 8.0%
##### 8.2%
###### 8.7%
如果你想在下載curl時報告“下載...”,你可能想要做這樣的事情(注意 - 有點高級的bash黑客攻擊):
curl "$url" -o "$outfile" -vs > >( # redirect stdout to sub-shell, note the space
# parse curl's "verbose" output which tells us what is happening
# while we use -s to silence the standard progress bar which is useless for this
while read line; do # read verbose progress messages
if grep -q "Connected" <<<"$line"; then # wait for curl to connect
echo "Downloading..."
break
fi
done
cat > /dev/null # make sure to consume all stdin if we break early, to prevent "broken pipe"
) 2>&1 || echo "Error!"
我使用進程替換將輸出定向到子shell的原因是不丟失curl退出代碼,如果出現錯誤則該代碼將為非零,允許我使用bash邏輯評估來報告錯誤(或者我可以只是從$?
捕獲它並檢查它 - curl有非常詳細的退出代碼報告,所以我可以弄清楚退出代碼出了什么問題。詳情請咨詢man curl
)。
還要注意2>&1
的位置,它將標准錯誤流重定向到標准輸出流,因此進程替換可以獲取通常發布到錯誤流的卷曲進度消息。 這個重定向必須在stdout捕獲之后,否則它只會創建一個stdout的副本,並且子shell將不會得到任何東西。 關於流復制的Bash手冊部分更好地解釋了這一點。
您在上面的代碼中有幾個問題:
*) 代替
... -o "`echo $filename`" ...
你應該這樣做
... -o "$filename" ...
當你想要做的就是讓bash擴展$filename
作為-o
參數的值時,沒有理由進行額外的間接-o
。
*)這沒有意義:
read <&1
文件描述符1
是標准輸出 - 你真的不想從中讀取。 如果你想從標准輸入讀取數據,就沒有什么可從重定向- read
默認情況下從標准輸入讀取。
*)這不是一個好習慣:
if [ "`echo $var | grep -o "value"`" == "value" ]; then
出於多種原因 - 首先, grep -o
幾乎沒用,尤其是簡單的文本搜索,因為它只會輸出您想要查找的內容(取決於是否找到了值),它完全映射到grep
退出代碼是0或1.所以相反, if echo $var | grep -q "value"; then
更好 if echo $var | grep -q "value"; then
if echo $var | grep -q "value"; then
。 如果grep
成功,則此表達式將成功,否則將失敗。 -q
用於使輸出靜音,因為您不需要它(只要它成功與否)。 此外,如果你有一個變量中的文本,使用echo
來獲取grep
只是煩人(它打開一個子shell和分叉和東西),而是說grep -q "value" <<<"$var"
。
最后,關於報告curl
是否正在下載,我個人認為curl
進度指標已經足夠好了,但如果它不是那么只需用-s
使其靜音。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.