簡體   English   中英

如何在“do”之后管道while循環輸入到封裝命令

[英]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 readcurl ,管道是空的。

知道我想直接將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM