2016-07-29 101 views
5

我有一個bash腳本,當在RHEL或OS X上運行,提供了以下錯誤:Bash腳本大小限制?

line 62484: syntax error near unexpected token `newline'

line 62484: ` -o_gz'

這是一個自動生成的腳本來解決在使用的網格引擎計算集羣引進的限制我的公司。它全部由一組幾乎相同的if/elif組成。我看不出錯誤來自哪裏。當我在錯誤行之前運行腳本的開始部分時,它沒有問題。這讓我覺得可能有一些bash腳本長度限制。我能在網上找到的唯一參考是comment by iAdjunct

圍繞錯誤的腳本的部分看起來像這樣(有一些簡化):

. 
. 
. 
. 
elif [ $task_number -eq 2499 ] 
then 
    /some/tool/executable \ 
    -use_prephased_g \ 
    -m \ 
    /some/text/file \ 
    -h \ 
    /some/zipped/file \ 
    -l \ 
    -int \ 
    45063854 \ 
    46063853 \ 
    -Ne \ 
    20000 \ 
    -o \ 
    /some/output/file \ 
    -verbose \ 
    -o_gz #==============> ****THIS IS LINE 62484**** 
elif [ $task_number -eq 2500 ] 
then 
    /some/tool/executable \ 
    -use_prephased_g \ 
    -m \ 
    /some/other/text/file \ 
    -h \ 
    /some/other/zipped/file \ 
    -l \ 
    -int \ 
    98232182 \ 
    99232182 \ 
    -Ne \ 
    20000 \ 
    -o \ 
    /some/other/output/file \ 
    -verbose \ 
    -o_gz 
elif [ $task_number -eq 2501 ] 
. 
. 
. 
. 

這是否響任何人任何鐘聲?

+0

嘗試http://www.shellcheck.net/ – Sundeep

+1

如果'elif's之間的唯一區別是* $ task_number *和三個* -int *和* -Ne *數字,並且'-m '和'-h'文件名,那麼它實際上是一個輸入一個變量的函數,並返回三個數字和兩個文件名。將所有四個數字和兩個文件名放在一個表或數組中,使一個函數返回所需的條件輸出會更簡單,然後腳本不需要* any *'if's或'elif's - 一個函數調用將完成數千個「elif」的工作。 – agc

回答

8

是的,這是bash的限制。

這不是腳本大小限制;相反,它是解析器堆棧的深度的限制,它會限制某些構造的複雜性。特別是,它會限制elif條款數量在if語句約2500

有這方面的問題相對於較長的分析,我的回答不同的語法結構(迭代管道)到a questionUnix & Linux stackexchange現場。

case聲明不具有此限制,您提供的示例看起來像case聲明的良好匹配。

(與case語句不同的是,對於if條件語句,這樣的管結構的語法,是正確的遞歸的,而對於case語句語法是左遞歸的。其理由上if陳述的限制是來自不同對於管道的限制是elif子句的語法結構還有一個符號,因此每個重複使用四個堆棧槽而不是三個)。

如果case語句不適用於您 - 或者即使它 - 您可以嘗試構建if語句的預編譯二叉搜索樹:

if ((task_number < 8)); then 
    if ((task_number < 4)); then 
    if ((task_number < 2)); then 
     if ((task_number < 1)); then 
     # do task 0 
     else 
     # do task 1 
     fi; 
    elif ((task_number < 3)); then 
     # do task 2 
    else 
     # do task 3 
    fi 
    elif ((task_number < 6)); then 
    if ((task_number < 5)); then 
     # do task 4 
    else 
     # do task 5 
    fi 
    elif ((task_number < 7)); then 
    # do task 6 
    else 
    # do task 7 
    fi 
elif ((task_number < 12)); then 
    if ((task_number < 10)); then 
    if ((task_number < 9)); then 
     # do task 8 
    else 
     # do task 9 
    fi 
    elif ((task_number < 11)); then 
    # do task 10 
    else 
    # do task 11 
    fi 
elif ((task_number < 14)); then 
    if ((task_number < 13)); then 
    # do task 12 
    else 
    # do task 13 
    fi 
elif ((task_number < 15)); then 
    # do task 14 
else 
    # do task 15 
fi 

因爲人們認識之後每完成if語句只佔用一個棧節點,複雜性的限制將在if語句,而不是條款的數量的嵌套深度。作爲額外的獎勵,它將在平均情況下執行少得多的比較。

如果你沒有比條件順序列表中的其他選擇,你可以使用不同的if聲明:

while :; do 
    if condition1; then 
    # do something 
    break; fi; if condition2; then 
    # do something 
    break; fi; if condition3; then 
    # do something 
    break; fi; if condition4; then 
    # do something 
    break; fi 
    # No alternative succeeded 
    break 
done 

的非常規縮進旨在說明簡單的程序轉換:簡單地用break;fi;if和更換每一個elifwhile環繞整個事物(以提供break的目標。)

+1

剛剛用1000萬行(250兆字節)腳本測試'bash' v4.3:'在{1..10000000}中爲f; echo'echo'「$ f」'>/dev/null';完成>> big.sh; bash big.sh'。它運行良好。編輯答案是更確定的這個*而不是腳本最大數量的行問題。 – agc